PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Calculation / Statistical / Distributions / Binomial.php

Binomial.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Calculation/Statistical/Distributions/Binomial.php

235 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
4
5 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Exception;
7 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Functions;
8 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
9 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Combinations;
10
11 class Binomial
12 {
13 use ArrayEnabled;
14
15 /**
16 * BINOMDIST.
17 *
18 * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with
19 * a fixed number of tests or trials, when the outcomes of any trial are only success or failure,
20 * when trials are independent, and when the probability of success is constant throughout the
21 * experiment. For example, BINOMDIST can calculate the probability that two of the next three
22 * babies born are male.
23 *
24 * @param mixed $value Integer number of successes in trials
25 * Or can be an array of values
26 * @param mixed $trials Integer umber of trials
27 * Or can be an array of values
28 * @param mixed $probability Probability of success on each trial as a float
29 * Or can be an array of values
30 * @param mixed $cumulative Boolean value indicating if we want the cdf (true) or the pdf (false)
31 * Or can be an array of values
32 *
33 * @return array<mixed>|float|string If an array of numbers is passed as an argument, then the returned result will also be an array
34 * with the same dimensions
35 */
36 public static function distribution($value, $trials, $probability, $cumulative)
37 {
38 if (is_array($value) || is_array($trials) || is_array($probability) || is_array($cumulative)) {
39 return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $trials, $probability, $cumulative);
40 }
41
42 try {
43 $value = DistributionValidations::validateInt($value);
44 $trials = DistributionValidations::validateInt($trials);
45 $probability = DistributionValidations::validateProbability($probability);
46 $cumulative = DistributionValidations::validateBool($cumulative);
47 } catch (Exception $e) {
48 return $e->getMessage();
49 }
50
51 if (($value < 0) || ($value > $trials)) {
52 return ExcelError::NAN();
53 }
54
55 if ($cumulative) {
56 return self::calculateCumulativeBinomial($value, $trials, $probability);
57 }
58 /** @var float $comb */
59 $comb = Combinations::withoutRepetition($trials, $value);
60
61 return $comb * $probability ** $value
62 * (1 - $probability) ** ($trials - $value);
63 }
64
65 /**
66 * BINOM.DIST.RANGE.
67 *
68 * Returns the Binomial Distribution probability for the number of successes from a specified number
69 * of trials falling into a specified range.
70 *
71 * @param mixed $trials Integer number of trials
72 * Or can be an array of values
73 * @param mixed $probability Probability of success on each trial as a float
74 * Or can be an array of values
75 * @param mixed $successes The integer number of successes in trials
76 * Or can be an array of values
77 * @param mixed $limit Upper limit for successes in trials as null, or an integer
78 * If null, then this will indicate the same as the number of Successes
79 * Or can be an array of values
80 *
81 * @return array<mixed>|float|int|string If an array of numbers is passed as an argument, then the returned result will also be an array
82 * with the same dimensions
83 */
84 public static function range($trials, $probability, $successes, $limit = null)
85 {
86 if (is_array($trials) || is_array($probability) || is_array($successes) || is_array($limit)) {
87 return self::evaluateArrayArguments([self::class, __FUNCTION__], $trials, $probability, $successes, $limit);
88 }
89
90 $limit = $limit ?? $successes;
91
92 try {
93 $trials = DistributionValidations::validateInt($trials);
94 $probability = DistributionValidations::validateProbability($probability);
95 $successes = DistributionValidations::validateInt($successes);
96 $limit = DistributionValidations::validateInt($limit);
97 } catch (Exception $e) {
98 return $e->getMessage();
99 }
100
101 if (($successes < 0) || ($successes > $trials)) {
102 return ExcelError::NAN();
103 }
104 if (($limit < 0) || ($limit > $trials) || $limit < $successes) {
105 return ExcelError::NAN();
106 }
107
108 $summer = 0;
109 for ($i = $successes; $i <= $limit; ++$i) {
110 /** @var float $comb */
111 $comb = Combinations::withoutRepetition($trials, $i);
112 $summer += $comb * $probability ** $i
113 * (1 - $probability) ** ($trials - $i);
114 }
115
116 return $summer;
117 }
118
119 /**
120 * NEGBINOMDIST.
121 *
122 * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that
123 * there will be number_f failures before the number_s-th success, when the constant
124 * probability of a success is probability_s. This function is similar to the binomial
125 * distribution, except that the number of successes is fixed, and the number of trials is
126 * variable. Like the binomial, trials are assumed to be independent.
127 *
128 * @param mixed $failures Number of Failures as an integer
129 * Or can be an array of values
130 * @param mixed $successes Threshold number of Successes as an integer
131 * Or can be an array of values
132 * @param mixed $probability Probability of success on each trial as a float
133 * Or can be an array of values
134 *
135 * @return array<mixed>|float|string The result, or a string containing an error
136 * If an array of numbers is passed as an argument, then the returned result will also be an array
137 * with the same dimensions
138 *
139 * TODO Add support for the cumulative flag not present for NEGBINOMDIST, but introduced for NEGBINOM.DIST
140 * The cumulative default should be false to reflect the behaviour of NEGBINOMDIST
141 */
142 public static function negative($failures, $successes, $probability)
143 {
144 if (is_array($failures) || is_array($successes) || is_array($probability)) {
145 return self::evaluateArrayArguments([self::class, __FUNCTION__], $failures, $successes, $probability);
146 }
147
148 try {
149 $failures = DistributionValidations::validateInt($failures);
150 $successes = DistributionValidations::validateInt($successes);
151 $probability = DistributionValidations::validateProbability($probability);
152 } catch (Exception $e) {
153 return $e->getMessage();
154 }
155
156 if (($failures < 0) || ($successes < 1)) {
157 return ExcelError::NAN();
158 }
159 if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
160 if (($failures + $successes - 1) <= 0) {
161 return ExcelError::NAN();
162 }
163 }
164 /** @var float $comb */
165 $comb = Combinations::withoutRepetition($failures + $successes - 1, $successes - 1);
166
167 return $comb
168 * ($probability ** $successes) * ((1 - $probability) ** $failures);
169 }
170
171 /**
172 * BINOM.INV.
173 *
174 * Returns the smallest value for which the cumulative binomial distribution is greater
175 * than or equal to a criterion value
176 *
177 * @param mixed $trials number of Bernoulli trials as an integer
178 * Or can be an array of values
179 * @param mixed $probability probability of a success on each trial as a float
180 * Or can be an array of values
181 * @param mixed $alpha criterion value as a float
182 * Or can be an array of values
183 *
184 * @return array<mixed>|int|string If an array of numbers is passed as an argument, then the returned result will also be an array
185 * with the same dimensions
186 */
187 public static function inverse($trials, $probability, $alpha)
188 {
189 if (is_array($trials) || is_array($probability) || is_array($alpha)) {
190 return self::evaluateArrayArguments([self::class, __FUNCTION__], $trials, $probability, $alpha);
191 }
192
193 try {
194 $trials = DistributionValidations::validateInt($trials);
195 $probability = DistributionValidations::validateProbability($probability);
196 $alpha = DistributionValidations::validateFloat($alpha);
197 } catch (Exception $e) {
198 return $e->getMessage();
199 }
200
201 if ($trials < 0) {
202 return ExcelError::NAN();
203 } elseif (($alpha < 0.0) || ($alpha > 1.0)) {
204 return ExcelError::NAN();
205 }
206
207 $successes = 0;
208 while ($successes <= $trials) {
209 $result = self::calculateCumulativeBinomial($successes, $trials, $probability);
210 if ($result >= $alpha) {
211 break;
212 }
213 ++$successes;
214 }
215
216 return $successes;
217 }
218
219 /**
220 * @return float|int
221 */
222 private static function calculateCumulativeBinomial(int $value, int $trials, float $probability)
223 {
224 $summer = 0;
225 for ($i = 0; $i <= $value; ++$i) {
226 /** @var float $comb */
227 $comb = Combinations::withoutRepetition($trials, $i);
228 $summer += $comb * $probability ** $i
229 * (1 - $probability) ** ($trials - $i);
230 }
231
232 return $summer;
233 }
234 }
235