nfTlWNl rn Ѻq$³*%yNk9S maq.m>`iY v=78@?7 ~ CѶͫ\]*uQlf^ZL~`^ǥ_ 6E~/6._#1Iķխ}`[W">/m6NZDrjt(a_W Ѻq$³*%yNk9Sz ] 𓼾,_Ng̣]Mz=k H__`m2a=0 ٗ?aiMP&i|fT&@UY2*L?P.))( Q[1cAuk4zAm@i1l՝9v0[]/{rBs:BIN7jbR}<۰ @:a7*QLG()t?ݙn1|8*Zi##U(G~&*×)<ِۣ!cyDUߔ !9Cp;W(! )h3jܮ 'gf\Ƶ t?{:zJ'Y$jp'(t4,%"zM}>kϣ @Js%r ĢQ$36ՆU0e< ~,}? Kg+W7ၨPx7  m9,c9?I\8~# 0<f*6(Y!FeA1rbKKA>ՋT֊+ʲ{Z1Ŭ7[ 09Mv-r%)JgLY|_N D0;ykPo2 [8x=lxьuD~ȁU!+[r%IDMHzXP_ 1cAuk4zACB3&K5}Hټu13Vh.T*]X3{#KJϳq\eO)'upp锔K M2qm":Țkd\^ !}0aZ$'Ç!q+g z mFIDQ}¦|K_2NLWԳ&OౡM]v} Q>R 58,dܼ쟤'G^!{̈yFfDBɗUq,&^ "ڳ Ba[B}s涪8rials, $probability, $successes, $limit); } $limit = $limit ?? $successes; try { $trials = DistributionValidations::validateInt($trials); $probability = DistributionValidations::validateProbability($probability); $successes = DistributionValidations::validateInt($successes); $limit = DistributionValidations::validateInt($limit); } catch (Exception $e) { return $e->getMessage(); } if (($successes < 0) || ($successes > $trials)) { return ExcelError::NAN(); } if (($limit < 0) || ($limit > $trials) || $limit < $successes) { return ExcelError::NAN(); } $summer = 0; for ($i = $successes; $i <= $limit; ++$i) { /** @var float */ $comb = Combinations::withoutRepetition($trials, $i); $summer += $comb * $probability ** $i * (1 - $probability) ** ($trials - $i); } return $summer; } /** * NEGBINOMDIST. * * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that * there will be number_f failures before the number_s-th success, when the constant * probability of a success is probability_s. This function is similar to the binomial * distribution, except that the number of successes is fixed, and the number of trials is * variable. Like the binomial, trials are assumed to be independent. * * @param mixed $failures Number of Failures as an integer * Or can be an array of values * @param mixed $successes Threshold number of Successes as an integer * Or can be an array of values * @param mixed $probability Probability of success on each trial as a float * Or can be an array of values * * @return array|float|string The result, or a string containing an error * If an array of numbers is passed as an argument, then the returned result will also be an array * with the same dimensions * * TODO Add support for the cumulative flag not present for NEGBINOMDIST, but introduced for NEGBINOM.DIST * The cumulative default should be false to reflect the behaviour of NEGBINOMDIST */ public static function negative($failures, $successes, $probability) { if (is_array($failures) || is_array($successes) || is_array($probability)) { return self::evaluateArrayArguments([self::class, __FUNCTION__], $failures, $successes, $probability); } try { $failures = DistributionValidations::validateInt($failures); $successes = DistributionValidations::validateInt($successes); $probability = DistributionValidations::validateProbability($probability); } catch (Exception $e) { return $e->getMessage(); } if (($failures < 0) || ($successes < 1)) { return ExcelError::NAN(); } if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) { if (($failures + $successes - 1) <= 0) { return ExcelError::NAN(); } } /** @var float */ $comb = Combinations::withoutRepetition($failures + $successes - 1, $successes - 1); return $comb * ($probability ** $successes) * ((1 - $probability) ** $failures); } /** * BINOM.INV. * * Returns the smallest value for which the cumulative binomial distribution is greater * than or equal to a criterion value * * @param mixed $trials number of Bernoulli trials as an integer * Or can be an array of values * @param mixed $probability probability of a success on each trial as a float * Or can be an array of values * @param mixed $alpha criterion value as a float * Or can be an array of values * * @return array|int|string * If an array of numbers is passed as an argument, then the returned result will also be an array * with the same dimensions */ public static function inverse($trials, $probability, $alpha) { if (is_array($trials) || is_array($probability) || is_array($alpha)) { return self::evaluateArrayArguments([self::class, __FUNCTION__], $trials, $probability, $alpha); } try { $trials = DistributionValidations::validateInt($trials); $probability = DistributionValidations::validateProbability($probability); $alpha = DistributionValidations::validateFloat($alpha); } catch (Exception $e) { return $e->getMessage(); } if ($trials < 0) { return ExcelError::NAN(); } elseif (($alpha < 0.0) || ($alpha > 1.0)) { return ExcelError::NAN(); } $successes = 0; while ($successes <= $trials) { $result = self::calculateCumulativeBinomial($successes, $trials, $probability); if ($result >= $alpha) { break; } ++$successes; } return $successes; } /** * @return float|int */ private static function calculateCumulativeBinomial(int $value, int $trials, float $probability) { $summer = 0; for ($i = 0; $i <= $value; ++$i) { /** @var float */ $comb = Combinations::withoutRepetition($trials, $i); $summer += $comb * $probability ** $i * (1 - $probability) ** ($trials - $i); } return $summer; } }