3
/** PHPExcel root directory */
4
if (!defined('PHPEXCEL_ROOT')) {
8
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
9
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
13
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/trendClass.php';
16
/** LOG_GAMMA_X_MAX_VALUE */
17
define('LOG_GAMMA_X_MAX_VALUE', 2.55e305);
20
define('XMININ', 2.23e-308);
23
define('EPS', 2.22e-16);
26
define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099);
29
* PHPExcel_Calculation_Statistical
31
* Copyright (c) 2006 - 2015 PHPExcel
33
* This library is free software; you can redistribute it and/or
34
* modify it under the terms of the GNU Lesser General Public
35
* License as published by the Free Software Foundation; either
36
* version 2.1 of the License, or (at your option) any later version.
38
* This library is distributed in the hope that it will be useful,
39
* but WITHOUT ANY WARRANTY; without even the implied warranty of
40
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41
* Lesser General Public License for more details.
43
* You should have received a copy of the GNU Lesser General Public
44
* License along with this library; if not, write to the Free Software
45
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
48
* @package PHPExcel_Calculation
49
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
50
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
51
* @version ##VERSION##, ##DATE##
53
class PHPExcel_Calculation_Statistical
55
private static function checkTrendArrays(&$array1, &$array2)
57
if (!is_array($array1)) {
58
$array1 = array($array1);
60
if (!is_array($array2)) {
61
$array2 = array($array2);
64
$array1 = PHPExcel_Calculation_Functions::flattenArray($array1);
65
$array2 = PHPExcel_Calculation_Functions::flattenArray($array2);
66
foreach ($array1 as $key => $value) {
67
if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
72
foreach ($array2 as $key => $value) {
73
if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
78
$array1 = array_merge($array1);
79
$array2 = array_merge($array2);
88
* @author Jaco van Kooten
90
* @param p require p>0
91
* @param q require q>0
92
* @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
94
private static function beta($p, $q)
96
if ($p <= 0.0 || $q <= 0.0 || ($p + $q) > LOG_GAMMA_X_MAX_VALUE) {
99
return exp(self::logBeta($p, $q));
105
* Incomplete beta function
107
* @author Jaco van Kooten
108
* @author Paul Meagher
110
* The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992).
111
* @param x require 0<=x<=1
112
* @param p require p>0
113
* @param q require q>0
114
* @return 0 if x<0, p<=0, q<=0 or p+q>2.55E305 and 1 if x>1 to avoid errors and over/underflow
116
private static function incompleteBeta($x, $p, $q)
120
} elseif ($x >= 1.0) {
122
} elseif (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
125
$beta_gam = exp((0 - self::logBeta($p, $q)) + $p * log($x) + $q * log(1.0 - $x));
126
if ($x < ($p + 1.0) / ($p + $q + 2.0)) {
127
return $beta_gam * self::betaFraction($x, $p, $q) / $p;
129
return 1.0 - ($beta_gam * self::betaFraction(1 - $x, $q, $p) / $q);
134
// Function cache for logBeta function
135
private static $logBetaCacheP = 0.0;
136
private static $logBetaCacheQ = 0.0;
137
private static $logBetaCacheResult = 0.0;
140
* The natural logarithm of the beta function.
142
* @param p require p>0
143
* @param q require q>0
144
* @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
145
* @author Jaco van Kooten
147
private static function logBeta($p, $q)
149
if ($p != self::$logBetaCacheP || $q != self::$logBetaCacheQ) {
150
self::$logBetaCacheP = $p;
151
self::$logBetaCacheQ = $q;
152
if (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
153
self::$logBetaCacheResult = 0.0;
155
self::$logBetaCacheResult = self::logGamma($p) + self::logGamma($q) - self::logGamma($p + $q);
158
return self::$logBetaCacheResult;
163
* Evaluates of continued fraction part of incomplete beta function.
164
* Based on an idea from Numerical Recipes (W.H. Press et al, 1992).
165
* @author Jaco van Kooten
167
private static function betaFraction($x, $p, $q)
173
$h = 1.0 - $sum_pq * $x / $p_plus;
174
if (abs($h) < XMININ) {
181
while ($m <= MAX_ITERATIONS && abs($delta-1.0) > PRECISION) {
184
$d = $m * ($q - $m) * $x / ( ($p_minus + $m2) * ($p + $m2));
186
if (abs($h) < XMININ) {
191
if (abs($c) < XMININ) {
196
$d = -($p + $m) * ($sum_pq + $m) * $x / (($p + $m2) * ($p_plus + $m2));
198
if (abs($h) < XMININ) {
203
if (abs($c) < XMININ) {
218
* @author Jaco van Kooten
220
* Original author was Jaco van Kooten. Ported to PHP by Paul Meagher.
222
* The natural logarithm of the gamma function. <br />
223
* Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz <br />
224
* Applied Mathematics Division <br />
225
* Argonne National Laboratory <br />
226
* Argonne, IL 60439 <br />
230
* <li>W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural
231
* Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203.</li>
232
* <li>K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969.</li>
233
* <li>Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968.</li>
237
* From the original documentation:
240
* This routine calculates the LOG(GAMMA) function for a positive real argument X.
241
* Computation is based on an algorithm outlined in references 1 and 2.
242
* The program uses rational functions that theoretically approximate LOG(GAMMA)
243
* to at least 18 significant decimal digits. The approximation for X > 12 is from
244
* reference 3, while approximations for X < 12.0 are similar to those in reference
245
* 1, but are unpublished. The accuracy achieved depends on the arithmetic system,
246
* the compiler, the intrinsic functions, and proper selection of the
247
* machine-dependent constants.
250
* Error returns: <br />
251
* The program returns the value XINF for X .LE. 0.0 or when overflow would occur.
252
* The computation is believed to be free of underflow and overflow.
254
* @return MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305
257
// Function cache for logGamma
258
private static $logGammaCacheResult = 0.0;
259
private static $logGammaCacheX = 0.0;
261
private static function logGamma($x)
263
// Log Gamma related constants
264
static $lg_d1 = -0.5772156649015328605195174;
265
static $lg_d2 = 0.4227843350984671393993777;
266
static $lg_d4 = 1.791759469228055000094023;
268
static $lg_p1 = array(
269
4.945235359296727046734888,
270
201.8112620856775083915565,
271
2290.838373831346393026739,
272
11319.67205903380828685045,
273
28557.24635671635335736389,
274
38484.96228443793359990269,
275
26377.48787624195437963534,
276
7225.813979700288197698961
278
static $lg_p2 = array(
279
4.974607845568932035012064,
280
542.4138599891070494101986,
281
15506.93864978364947665077,
282
184793.2904445632425417223,
283
1088204.76946882876749847,
284
3338152.967987029735917223,
285
5106661.678927352456275255,
286
3074109.054850539556250927
288
static $lg_p4 = array(
289
14745.02166059939948905062,
290
2426813.369486704502836312,
291
121475557.4045093227939592,
292
2663432449.630976949898078,
293
29403789566.34553899906876,
294
170266573776.5398868392998,
295
492612579337.743088758812,
296
560625185622.3951465078242
298
static $lg_q1 = array(
299
67.48212550303777196073036,
300
1113.332393857199323513008,
301
7738.757056935398733233834,
302
27639.87074403340708898585,
303
54993.10206226157329794414,
304
61611.22180066002127833352,
305
36351.27591501940507276287,
306
8785.536302431013170870835
308
static $lg_q2 = array(
309
183.0328399370592604055942,
310
7765.049321445005871323047,
311
133190.3827966074194402448,
312
1136705.821321969608938755,
313
5267964.117437946917577538,
314
13467014.54311101692290052,
315
17827365.30353274213975932,
316
9533095.591844353613395747
318
static $lg_q4 = array(
319
2690.530175870899333379843,
320
639388.5654300092398984238,
321
41355999.30241388052042842,
322
1120872109.61614794137657,
323
14886137286.78813811542398,
324
101680358627.2438228077304,
325
341747634550.7377132798597,
326
446315818741.9713286462081
328
static $lg_c = array(
331
-5.952379913043012e-4,
332
7.93650793500350248e-4,
333
-0.002777777777777681622553,
334
0.08333333333333333331554247,
338
// Rough estimate of the fourth root of logGamma_xBig
339
static $lg_frtbig = 2.25e76;
340
static $pnt68 = 0.6796875;
343
if ($x == self::$logGammaCacheX) {
344
return self::$logGammaCacheResult;
347
if ($y > 0.0 && $y <= LOG_GAMMA_X_MAX_VALUE) {
350
} elseif ($y <= 1.5) {
351
// ---------------------
352
// EPS .LT. X .LE. 1.5
353
// ---------------------
361
if ($y <= 0.5 || $y >= $pnt68) {
364
for ($i = 0; $i < 8; ++$i) {
365
$xnum = $xnum * $xm1 + $lg_p1[$i];
366
$xden = $xden * $xm1 + $lg_q1[$i];
368
$res = $corr + $xm1 * ($lg_d1 + $xm1 * ($xnum / $xden));
373
for ($i = 0; $i < 8; ++$i) {
374
$xnum = $xnum * $xm2 + $lg_p2[$i];
375
$xden = $xden * $xm2 + $lg_q2[$i];
377
$res = $corr + $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
379
} elseif ($y <= 4.0) {
380
// ---------------------
381
// 1.5 .LT. X .LE. 4.0
382
// ---------------------
386
for ($i = 0; $i < 8; ++$i) {
387
$xnum = $xnum * $xm2 + $lg_p2[$i];
388
$xden = $xden * $xm2 + $lg_q2[$i];
390
$res = $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
391
} elseif ($y <= 12.0) {
392
// ----------------------
393
// 4.0 .LT. X .LE. 12.0
394
// ----------------------
398
for ($i = 0; $i < 8; ++$i) {
399
$xnum = $xnum * $xm4 + $lg_p4[$i];
400
$xden = $xden * $xm4 + $lg_q4[$i];
402
$res = $lg_d4 + $xm4 * ($xnum / $xden);
404
// ---------------------------------
405
// Evaluate for argument .GE. 12.0
406
// ---------------------------------
408
if ($y <= $lg_frtbig) {
411
for ($i = 0; $i < 6; ++$i) {
412
$res = $res / $ysq + $lg_c[$i];
416
$res = $res + log(SQRT2PI) - 0.5 * $corr;
417
$res += $y * ($corr - 1.0);
421
// --------------------------
422
// Return for bad arguments
423
// --------------------------
426
// ------------------------------
427
// Final adjustments and return
428
// ------------------------------
429
self::$logGammaCacheX = $x;
430
self::$logGammaCacheResult = $res;
436
// Private implementation of the incomplete Gamma function
438
private static function incompleteGamma($a, $x)
442
for ($n=0; $n<=$max; ++$n) {
444
for ($i=1; $i<=$n; ++$i) {
445
$divisor *= ($a + $i);
447
$summer += (pow($x, $n) / $divisor);
449
return pow($x, $a) * exp(0-$x) * $summer;
454
// Private implementation of the Gamma function
456
private static function gamma($data)
462
static $p0 = 1.000000000190015;
464
1 => 76.18009172947146,
465
2 => -86.50532032941677,
466
3 => 24.01409824083091,
467
4 => -1.231739572450155,
468
5 => 1.208650973866179e-3,
469
6 => -5.395239384953e-6
474
$tmp -= ($x + 0.5) * log($tmp);
477
for ($j=1; $j<=6; ++$j) {
478
$summer += ($p[$j] / ++$y);
480
return exp(0 - $tmp + log(SQRT2PI * $summer / $x));
484
/***************************************************************************
486
* -------------------
487
* begin : Friday, January 16, 2004
488
* copyright : (C) 2004 Michael Nickerson
489
* email : nickersonm@yahoo.com
491
***************************************************************************/
492
private static function inverseNcdf($p)
494
// Inverse ncdf approximation by Peter J. Acklam, implementation adapted to
495
// PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as
496
// a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html
497
// I have not checked the accuracy of this implementation. Be aware that PHP
498
// will truncate the coeficcients to 14 digits.
500
// You have permission to use and distribute this function freely for
501
// whatever purpose you want, but please show common courtesy and give credit
502
// where credit is due.
504
// Input paramater is $p - probability - where 0 < p < 1.
506
// Coefficients in rational approximations
508
1 => -3.969683028665376e+01,
509
2 => 2.209460984245205e+02,
510
3 => -2.759285104469687e+02,
511
4 => 1.383577518672690e+02,
512
5 => -3.066479806614716e+01,
513
6 => 2.506628277459239e+00
517
1 => -5.447609879822406e+01,
518
2 => 1.615858368580409e+02,
519
3 => -1.556989798598866e+02,
520
4 => 6.680131188771972e+01,
521
5 => -1.328068155288572e+01
525
1 => -7.784894002430293e-03,
526
2 => -3.223964580411365e-01,
527
3 => -2.400758277161838e+00,
528
4 => -2.549732539343734e+00,
529
5 => 4.374664141464968e+00,
530
6 => 2.938163982698783e+00
534
1 => 7.784695709041462e-03,
535
2 => 3.224671290700398e-01,
536
3 => 2.445134137142996e+00,
537
4 => 3.754408661907416e+00
540
// Define lower and upper region break-points.
541
$p_low = 0.02425; //Use lower region approx. below this
542
$p_high = 1 - $p_low; //Use upper region approx. above this
544
if (0 < $p && $p < $p_low) {
545
// Rational approximation for lower region.
546
$q = sqrt(-2 * log($p));
547
return ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
548
(((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
549
} elseif ($p_low <= $p && $p <= $p_high) {
550
// Rational approximation for central region.
553
return ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q /
554
((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1);
555
} elseif ($p_high < $p && $p < 1) {
556
// Rational approximation for upper region.
557
$q = sqrt(-2 * log(1 - $p));
558
return -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
559
(((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
561
// If 0 < p < 1, return a null value
562
return PHPExcel_Calculation_Functions::NULL();
566
private static function inverseNcdf2($prob)
568
// Approximation of inverse standard normal CDF developed by
569
// B. Moro, "The Full Monte," Risk 8(2), Feb 1995, 57-58.
572
$a2 = -18.61500062529;
573
$a3 = 41.39119773534;
574
$a4 = -25.44106049637;
577
$b2 = 23.08336743743;
578
$b3 = -21.06224101826;
581
$c1 = 0.337475482272615;
582
$c2 = 0.976169019091719;
583
$c3 = 0.160797971491821;
584
$c4 = 2.76438810333863E-02;
585
$c5 = 3.8405729373609E-03;
586
$c6 = 3.951896511919E-04;
587
$c7 = 3.21767881768E-05;
588
$c8 = 2.888167364E-07;
589
$c9 = 3.960315187E-07;
592
if (abs($y) < 0.42) {
594
$z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1);
597
$z = log(-log(1 - $prob));
599
$z = log(-log($prob));
601
$z = $c1 + $z * ($c2 + $z * ($c3 + $z * ($c4 + $z * ($c5 + $z * ($c6 + $z * ($c7 + $z * ($c8 + $z * $c9)))))));
607
} // function inverseNcdf2()
610
private static function inverseNcdf3($p)
612
// ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3.
613
// Produces the normal deviate Z corresponding to a given lower
614
// tail area of P; Z is accurate to about 1 part in 10**16.
616
// This is a PHP version of the original FORTRAN code that can
617
// be found at http://lib.stat.cmu.edu/apstat/
623
// coefficients for p close to 0.5
624
$a0 = 3.3871328727963666080;
625
$a1 = 1.3314166789178437745E+2;
626
$a2 = 1.9715909503065514427E+3;
627
$a3 = 1.3731693765509461125E+4;
628
$a4 = 4.5921953931549871457E+4;
629
$a5 = 6.7265770927008700853E+4;
630
$a6 = 3.3430575583588128105E+4;
631
$a7 = 2.5090809287301226727E+3;
633
$b1 = 4.2313330701600911252E+1;
634
$b2 = 6.8718700749205790830E+2;
635
$b3 = 5.3941960214247511077E+3;
636
$b4 = 2.1213794301586595867E+4;
637
$b5 = 3.9307895800092710610E+4;
638
$b6 = 2.8729085735721942674E+4;
639
$b7 = 5.2264952788528545610E+3;
641
// coefficients for p not close to 0, 0.5 or 1.
642
$c0 = 1.42343711074968357734;
643
$c1 = 4.63033784615654529590;
644
$c2 = 5.76949722146069140550;
645
$c3 = 3.64784832476320460504;
646
$c4 = 1.27045825245236838258;
647
$c5 = 2.41780725177450611770E-1;
648
$c6 = 2.27238449892691845833E-2;
649
$c7 = 7.74545014278341407640E-4;
651
$d1 = 2.05319162663775882187;
652
$d2 = 1.67638483018380384940;
653
$d3 = 6.89767334985100004550E-1;
654
$d4 = 1.48103976427480074590E-1;
655
$d5 = 1.51986665636164571966E-2;
656
$d6 = 5.47593808499534494600E-4;
657
$d7 = 1.05075007164441684324E-9;
659
// coefficients for p near 0 or 1.
660
$e0 = 6.65790464350110377720;
661
$e1 = 5.46378491116411436990;
662
$e2 = 1.78482653991729133580;
663
$e3 = 2.96560571828504891230E-1;
664
$e4 = 2.65321895265761230930E-2;
665
$e5 = 1.24266094738807843860E-3;
666
$e6 = 2.71155556874348757815E-5;
667
$e7 = 2.01033439929228813265E-7;
669
$f1 = 5.99832206555887937690E-1;
670
$f2 = 1.36929880922735805310E-1;
671
$f3 = 1.48753612908506148525E-2;
672
$f4 = 7.86869131145613259100E-4;
673
$f5 = 1.84631831751005468180E-5;
674
$f6 = 1.42151175831644588870E-7;
675
$f7 = 2.04426310338993978564E-15;
679
// computation for p close to 0.5
680
if (abs($q) <= split1) {
681
$R = $const1 - $q * $q;
682
$z = $q * ((((((($a7 * $R + $a6) * $R + $a5) * $R + $a4) * $R + $a3) * $R + $a2) * $R + $a1) * $R + $a0) /
683
((((((($b7 * $R + $b6) * $R + $b5) * $R + $b4) * $R + $b3) * $R + $b2) * $R + $b1) * $R + 1);
690
$R = pow(-log($R), 2);
692
// computation for p not close to 0, 0.5 or 1.
695
$z = ((((((($c7 * $R + $c6) * $R + $c5) * $R + $c4) * $R + $c3) * $R + $c2) * $R + $c1) * $R + $c0) /
696
((((((($d7 * $R + $d6) * $R + $d5) * $R + $d4) * $R + $d3) * $R + $d2) * $R + $d1) * $R + 1);
698
// computation for p near 0 or 1.
700
$z = ((((((($e7 * $R + $e6) * $R + $e5) * $R + $e4) * $R + $e3) * $R + $e2) * $R + $e1) * $R + $e0) /
701
((((((($f7 * $R + $f6) * $R + $f5) * $R + $f4) * $R + $f3) * $R + $f2) * $R + $f1) * $R + 1);
714
* Returns the average of the absolute deviations of data points from their mean.
715
* AVEDEV is a measure of the variability in a data set.
718
* AVEDEV(value1[,value2[, ...]])
721
* @category Statistical Functions
722
* @param mixed $arg,... Data values
725
public static function AVEDEV()
727
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
732
$aMean = self::AVERAGE($aArgs);
733
if ($aMean != PHPExcel_Calculation_Functions::DIV0()) {
735
foreach ($aArgs as $k => $arg) {
736
if ((is_bool($arg)) &&
737
((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
738
$arg = (integer) $arg;
740
// Is it a numeric value?
741
if ((is_numeric($arg)) && (!is_string($arg))) {
742
if (is_null($returnValue)) {
743
$returnValue = abs($arg - $aMean);
745
$returnValue += abs($arg - $aMean);
753
return PHPExcel_Calculation_Functions::DIV0();
755
return $returnValue / $aCount;
757
return PHPExcel_Calculation_Functions::NaN();
764
* Returns the average (arithmetic mean) of the arguments
767
* AVERAGE(value1[,value2[, ...]])
770
* @category Statistical Functions
771
* @param mixed $arg,... Data values
774
public static function AVERAGE()
776
$returnValue = $aCount = 0;
778
// Loop through arguments
779
foreach (PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
780
if ((is_bool($arg)) &&
781
((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
782
$arg = (integer) $arg;
784
// Is it a numeric value?
785
if ((is_numeric($arg)) && (!is_string($arg))) {
786
if (is_null($returnValue)) {
789
$returnValue += $arg;
797
return $returnValue / $aCount;
799
return PHPExcel_Calculation_Functions::DIV0();
807
* Returns the average of its arguments, including numbers, text, and logical values
810
* AVERAGEA(value1[,value2[, ...]])
813
* @category Statistical Functions
814
* @param mixed $arg,... Data values
817
public static function AVERAGEA()
822
// Loop through arguments
823
foreach (PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
824
if ((is_bool($arg)) &&
825
(!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
827
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
829
$arg = (integer) $arg;
830
} elseif (is_string($arg)) {
833
if (is_null($returnValue)) {
836
$returnValue += $arg;
844
return $returnValue / $aCount;
846
return PHPExcel_Calculation_Functions::DIV0();
854
* Returns the average value from a range of cells that contain numbers within the list of arguments
857
* AVERAGEIF(value1[,value2[, ...]],condition)
860
* @category Mathematical and Trigonometric Functions
861
* @param mixed $arg,... Data values
862
* @param string $condition The criteria that defines which cells will be checked.
863
* @param mixed[] $averageArgs Data values
866
public static function AVERAGEIF($aArgs, $condition, $averageArgs = array())
870
$aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
871
$averageArgs = PHPExcel_Calculation_Functions::flattenArray($averageArgs);
872
if (empty($averageArgs)) {
873
$averageArgs = $aArgs;
875
$condition = PHPExcel_Calculation_Functions::ifCondition($condition);
876
// Loop through arguments
878
foreach ($aArgs as $key => $arg) {
879
if (!is_numeric($arg)) {
880
$arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
882
$testCondition = '='.$arg.$condition;
883
if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
884
if ((is_null($returnValue)) || ($arg > $returnValue)) {
885
$returnValue += $arg;
892
return $returnValue / $aCount;
894
return PHPExcel_Calculation_Functions::DIV0();
901
* Returns the beta distribution.
903
* @param float $value Value at which you want to evaluate the distribution
904
* @param float $alpha Parameter to the distribution
905
* @param float $beta Parameter to the distribution
906
* @param boolean $cumulative
910
public static function BETADIST($value, $alpha, $beta, $rMin = 0, $rMax = 1)
912
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
913
$alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
914
$beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
915
$rMin = PHPExcel_Calculation_Functions::flattenSingleValue($rMin);
916
$rMax = PHPExcel_Calculation_Functions::flattenSingleValue($rMax);
918
if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
919
if (($value < $rMin) || ($value > $rMax) || ($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax)) {
920
return PHPExcel_Calculation_Functions::NaN();
928
$value /= ($rMax - $rMin);
929
return self::incompleteBeta($value, $alpha, $beta);
931
return PHPExcel_Calculation_Functions::VALUE();
938
* Returns the inverse of the beta distribution.
940
* @param float $probability Probability at which you want to evaluate the distribution
941
* @param float $alpha Parameter to the distribution
942
* @param float $beta Parameter to the distribution
943
* @param float $rMin Minimum value
944
* @param float $rMax Maximum value
945
* @param boolean $cumulative
949
public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1)
951
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
952
$alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
953
$beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
954
$rMin = PHPExcel_Calculation_Functions::flattenSingleValue($rMin);
955
$rMax = PHPExcel_Calculation_Functions::flattenSingleValue($rMax);
957
if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
958
if (($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax) || ($probability <= 0) || ($probability > 1)) {
959
return PHPExcel_Calculation_Functions::NaN();
970
while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
971
$guess = ($a + $b) / 2;
972
$result = self::BETADIST($guess, $alpha, $beta);
973
if (($result == $probability) || ($result == 0)) {
975
} elseif ($result > $probability) {
981
if ($i == MAX_ITERATIONS) {
982
return PHPExcel_Calculation_Functions::NA();
984
return round($rMin + $guess * ($rMax - $rMin), 12);
986
return PHPExcel_Calculation_Functions::VALUE();
993
* Returns the individual term binomial distribution probability. Use BINOMDIST in problems with
994
* a fixed number of tests or trials, when the outcomes of any trial are only success or failure,
995
* when trials are independent, and when the probability of success is constant throughout the
996
* experiment. For example, BINOMDIST can calculate the probability that two of the next three
997
* babies born are male.
999
* @param float $value Number of successes in trials
1000
* @param float $trials Number of trials
1001
* @param float $probability Probability of success on each trial
1002
* @param boolean $cumulative
1005
* @todo Cumulative distribution function
1008
public static function BINOMDIST($value, $trials, $probability, $cumulative)
1010
$value = floor(PHPExcel_Calculation_Functions::flattenSingleValue($value));
1011
$trials = floor(PHPExcel_Calculation_Functions::flattenSingleValue($trials));
1012
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
1014
if ((is_numeric($value)) && (is_numeric($trials)) && (is_numeric($probability))) {
1015
if (($value < 0) || ($value > $trials)) {
1016
return PHPExcel_Calculation_Functions::NaN();
1018
if (($probability < 0) || ($probability > 1)) {
1019
return PHPExcel_Calculation_Functions::NaN();
1021
if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1024
for ($i = 0; $i <= $value; ++$i) {
1025
$summer += PHPExcel_Calculation_MathTrig::COMBIN($trials, $i) * pow($probability, $i) * pow(1 - $probability, $trials - $i);
1029
return PHPExcel_Calculation_MathTrig::COMBIN($trials, $value) * pow($probability, $value) * pow(1 - $probability, $trials - $value) ;
1033
return PHPExcel_Calculation_Functions::VALUE();
1040
* Returns the one-tailed probability of the chi-squared distribution.
1042
* @param float $value Value for the function
1043
* @param float $degrees degrees of freedom
1046
public static function CHIDIST($value, $degrees)
1048
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
1049
$degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
1051
if ((is_numeric($value)) && (is_numeric($degrees))) {
1053
return PHPExcel_Calculation_Functions::NaN();
1056
if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
1059
return PHPExcel_Calculation_Functions::NaN();
1061
return 1 - (self::incompleteGamma($degrees/2, $value/2) / self::gamma($degrees/2));
1063
return PHPExcel_Calculation_Functions::VALUE();
1070
* Returns the one-tailed probability of the chi-squared distribution.
1072
* @param float $probability Probability for the function
1073
* @param float $degrees degrees of freedom
1076
public static function CHIINV($probability, $degrees)
1078
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
1079
$degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
1081
if ((is_numeric($probability)) && (is_numeric($degrees))) {
1089
while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
1090
// Apply Newton-Raphson step
1091
$result = self::CHIDIST($x, $degrees);
1092
$error = $result - $probability;
1093
if ($error == 0.0) {
1095
} elseif ($error < 0.0) {
1100
// Avoid division by zero
1101
if ($result != 0.0) {
1102
$dx = $error / $result;
1105
// If the NR fails to converge (which for example may be the
1106
// case if the initial guess is too rough) we apply a bisection
1107
// step to determine a more narrow interval around the root.
1108
if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
1109
$xNew = ($xLo + $xHi) / 2;
1114
if ($i == MAX_ITERATIONS) {
1115
return PHPExcel_Calculation_Functions::NA();
1117
return round($x, 12);
1119
return PHPExcel_Calculation_Functions::VALUE();
1126
* Returns the confidence interval for a population mean
1128
* @param float $alpha
1129
* @param float $stdDev Standard Deviation
1130
* @param float $size
1134
public static function CONFIDENCE($alpha, $stdDev, $size)
1136
$alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
1137
$stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
1138
$size = floor(PHPExcel_Calculation_Functions::flattenSingleValue($size));
1140
if ((is_numeric($alpha)) && (is_numeric($stdDev)) && (is_numeric($size))) {
1141
if (($alpha <= 0) || ($alpha >= 1)) {
1142
return PHPExcel_Calculation_Functions::NaN();
1144
if (($stdDev <= 0) || ($size < 1)) {
1145
return PHPExcel_Calculation_Functions::NaN();
1147
return self::NORMSINV(1 - $alpha / 2) * $stdDev / sqrt($size);
1149
return PHPExcel_Calculation_Functions::VALUE();
1156
* Returns covariance, the average of the products of deviations for each data point pair.
1158
* @param array of mixed Data Series Y
1159
* @param array of mixed Data Series X
1162
public static function CORREL($yValues, $xValues = null)
1164
if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) {
1165
return PHPExcel_Calculation_Functions::VALUE();
1167
if (!self::checkTrendArrays($yValues, $xValues)) {
1168
return PHPExcel_Calculation_Functions::VALUE();
1170
$yValueCount = count($yValues);
1171
$xValueCount = count($xValues);
1173
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1174
return PHPExcel_Calculation_Functions::NA();
1175
} elseif ($yValueCount == 1) {
1176
return PHPExcel_Calculation_Functions::DIV0();
1179
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
1180
return $bestFitLinear->getCorrelation();
1187
* Counts the number of cells that contain numbers within the list of arguments
1190
* COUNT(value1[,value2[, ...]])
1193
* @category Statistical Functions
1194
* @param mixed $arg,... Data values
1197
public static function COUNT()
1201
// Loop through arguments
1202
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
1203
foreach ($aArgs as $k => $arg) {
1204
if ((is_bool($arg)) &&
1205
((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
1206
$arg = (integer) $arg;
1208
// Is it a numeric value?
1209
if ((is_numeric($arg)) && (!is_string($arg))) {
1214
return $returnValue;
1221
* Counts the number of cells that are not empty within the list of arguments
1224
* COUNTA(value1[,value2[, ...]])
1227
* @category Statistical Functions
1228
* @param mixed $arg,... Data values
1231
public static function COUNTA()
1235
// Loop through arguments
1236
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
1237
foreach ($aArgs as $arg) {
1238
// Is it a numeric, boolean or string value?
1239
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
1244
return $returnValue;
1251
* Counts the number of empty cells within the list of arguments
1254
* COUNTBLANK(value1[,value2[, ...]])
1257
* @category Statistical Functions
1258
* @param mixed $arg,... Data values
1261
public static function COUNTBLANK()
1265
// Loop through arguments
1266
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
1267
foreach ($aArgs as $arg) {
1268
// Is it a blank cell?
1269
if ((is_null($arg)) || ((is_string($arg)) && ($arg == ''))) {
1274
return $returnValue;
1281
* Counts the number of cells that contain numbers within the list of arguments
1284
* COUNTIF(value1[,value2[, ...]],condition)
1287
* @category Statistical Functions
1288
* @param mixed $arg,... Data values
1289
* @param string $condition The criteria that defines which cells will be counted.
1292
public static function COUNTIF($aArgs, $condition)
1296
$aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
1297
$condition = PHPExcel_Calculation_Functions::ifCondition($condition);
1298
// Loop through arguments
1299
foreach ($aArgs as $arg) {
1300
if (!is_numeric($arg)) {
1301
$arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
1303
$testCondition = '='.$arg.$condition;
1304
if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
1305
// Is it a value within our criteria
1310
return $returnValue;
1317
* Returns covariance, the average of the products of deviations for each data point pair.
1319
* @param array of mixed Data Series Y
1320
* @param array of mixed Data Series X
1323
public static function COVAR($yValues, $xValues)
1325
if (!self::checkTrendArrays($yValues, $xValues)) {
1326
return PHPExcel_Calculation_Functions::VALUE();
1328
$yValueCount = count($yValues);
1329
$xValueCount = count($xValues);
1331
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1332
return PHPExcel_Calculation_Functions::NA();
1333
} elseif ($yValueCount == 1) {
1334
return PHPExcel_Calculation_Functions::DIV0();
1337
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
1338
return $bestFitLinear->getCovariance();
1345
* Returns the smallest value for which the cumulative binomial distribution is greater
1346
* than or equal to a criterion value
1348
* See http://support.microsoft.com/kb/828117/ for details of the algorithm used
1350
* @param float $trials number of Bernoulli trials
1351
* @param float $probability probability of a success on each trial
1352
* @param float $alpha criterion value
1355
* @todo Warning. This implementation differs from the algorithm detailed on the MS
1356
* web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess
1357
* This eliminates a potential endless loop error, but may have an adverse affect on the
1358
* accuracy of the function (although all my tests have so far returned correct results).
1361
public static function CRITBINOM($trials, $probability, $alpha)
1363
$trials = floor(PHPExcel_Calculation_Functions::flattenSingleValue($trials));
1364
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
1365
$alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
1367
if ((is_numeric($trials)) && (is_numeric($probability)) && (is_numeric($alpha))) {
1369
return PHPExcel_Calculation_Functions::NaN();
1370
} elseif (($probability < 0) || ($probability > 1)) {
1371
return PHPExcel_Calculation_Functions::NaN();
1372
} elseif (($alpha < 0) || ($alpha > 1)) {
1373
return PHPExcel_Calculation_Functions::NaN();
1374
} elseif ($alpha <= 0.5) {
1375
$t = sqrt(log(1 / ($alpha * $alpha)));
1376
$trialsApprox = 0 - ($t + (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t));
1378
$t = sqrt(log(1 / pow(1 - $alpha, 2)));
1379
$trialsApprox = $t - (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t);
1381
$Guess = floor($trials * $probability + $trialsApprox * sqrt($trials * $probability * (1 - $probability)));
1384
} elseif ($Guess > $trials) {
1388
$TotalUnscaledProbability = $UnscaledPGuess = $UnscaledCumPGuess = 0.0;
1389
$EssentiallyZero = 10e-12;
1391
$m = floor($trials * $probability);
1392
++$TotalUnscaledProbability;
1397
++$UnscaledCumPGuess;
1403
while ((!$Done) && ($k <= $trials)) {
1404
$CurrentValue = $PreviousValue * ($trials - $k + 1) * $probability / ($k * (1 - $probability));
1405
$TotalUnscaledProbability += $CurrentValue;
1407
$UnscaledPGuess += $CurrentValue;
1410
$UnscaledCumPGuess += $CurrentValue;
1412
if ($CurrentValue <= $EssentiallyZero) {
1415
$PreviousValue = $CurrentValue;
1422
while ((!$Done) && ($k >= 0)) {
1423
$CurrentValue = $PreviousValue * $k + 1 * (1 - $probability) / (($trials - $k) * $probability);
1424
$TotalUnscaledProbability += $CurrentValue;
1426
$UnscaledPGuess += $CurrentValue;
1429
$UnscaledCumPGuess += $CurrentValue;
1431
if ($CurrentValue <= $EssentiallyZero) {
1434
$PreviousValue = $CurrentValue;
1438
$PGuess = $UnscaledPGuess / $TotalUnscaledProbability;
1439
$CumPGuess = $UnscaledCumPGuess / $TotalUnscaledProbability;
1441
// $CumPGuessMinus1 = $CumPGuess - $PGuess;
1442
$CumPGuessMinus1 = $CumPGuess - 1;
1445
if (($CumPGuessMinus1 < $alpha) && ($CumPGuess >= $alpha)) {
1447
} elseif (($CumPGuessMinus1 < $alpha) && ($CumPGuess < $alpha)) {
1448
$PGuessPlus1 = $PGuess * ($trials - $Guess) * $probability / $Guess / (1 - $probability);
1449
$CumPGuessMinus1 = $CumPGuess;
1450
$CumPGuess = $CumPGuess + $PGuessPlus1;
1451
$PGuess = $PGuessPlus1;
1453
} elseif (($CumPGuessMinus1 >= $alpha) && ($CumPGuess >= $alpha)) {
1454
$PGuessMinus1 = $PGuess * $Guess * (1 - $probability) / ($trials - $Guess + 1) / $probability;
1455
$CumPGuess = $CumPGuessMinus1;
1456
$CumPGuessMinus1 = $CumPGuessMinus1 - $PGuess;
1457
$PGuess = $PGuessMinus1;
1462
return PHPExcel_Calculation_Functions::VALUE();
1469
* Returns the sum of squares of deviations of data points from their sample mean.
1472
* DEVSQ(value1[,value2[, ...]])
1475
* @category Statistical Functions
1476
* @param mixed $arg,... Data values
1479
public static function DEVSQ()
1481
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
1484
$returnValue = null;
1486
$aMean = self::AVERAGE($aArgs);
1487
if ($aMean != PHPExcel_Calculation_Functions::DIV0()) {
1489
foreach ($aArgs as $k => $arg) {
1490
// Is it a numeric value?
1491
if ((is_bool($arg)) &&
1492
((!PHPExcel_Calculation_Functions::isCellValue($k)) ||
1493
(PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
1494
$arg = (integer) $arg;
1496
if ((is_numeric($arg)) && (!is_string($arg))) {
1497
if (is_null($returnValue)) {
1498
$returnValue = pow(($arg - $aMean), 2);
1500
$returnValue += pow(($arg - $aMean), 2);
1507
if (is_null($returnValue)) {
1508
return PHPExcel_Calculation_Functions::NaN();
1510
return $returnValue;
1520
* Returns the exponential distribution. Use EXPONDIST to model the time between events,
1521
* such as how long an automated bank teller takes to deliver cash. For example, you can
1522
* use EXPONDIST to determine the probability that the process takes at most 1 minute.
1524
* @param float $value Value of the function
1525
* @param float $lambda The parameter value
1526
* @param boolean $cumulative
1529
public static function EXPONDIST($value, $lambda, $cumulative)
1531
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
1532
$lambda = PHPExcel_Calculation_Functions::flattenSingleValue($lambda);
1533
$cumulative = PHPExcel_Calculation_Functions::flattenSingleValue($cumulative);
1535
if ((is_numeric($value)) && (is_numeric($lambda))) {
1536
if (($value < 0) || ($lambda < 0)) {
1537
return PHPExcel_Calculation_Functions::NaN();
1539
if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1541
return 1 - exp(0-$value*$lambda);
1543
return $lambda * exp(0-$value*$lambda);
1547
return PHPExcel_Calculation_Functions::VALUE();
1554
* Returns the Fisher transformation at x. This transformation produces a function that
1555
* is normally distributed rather than skewed. Use this function to perform hypothesis
1556
* testing on the correlation coefficient.
1558
* @param float $value
1561
public static function FISHER($value)
1563
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
1565
if (is_numeric($value)) {
1566
if (($value <= -1) || ($value >= 1)) {
1567
return PHPExcel_Calculation_Functions::NaN();
1569
return 0.5 * log((1+$value)/(1-$value));
1571
return PHPExcel_Calculation_Functions::VALUE();
1578
* Returns the inverse of the Fisher transformation. Use this transformation when
1579
* analyzing correlations between ranges or arrays of data. If y = FISHER(x), then
1582
* @param float $value
1585
public static function FISHERINV($value)
1587
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
1589
if (is_numeric($value)) {
1590
return (exp(2 * $value) - 1) / (exp(2 * $value) + 1);
1592
return PHPExcel_Calculation_Functions::VALUE();
1599
* Calculates, or predicts, a future value by using existing values. The predicted value is a y-value for a given x-value.
1601
* @param float Value of X for which we want to find Y
1602
* @param array of mixed Data Series Y
1603
* @param array of mixed Data Series X
1606
public static function FORECAST($xValue, $yValues, $xValues)
1608
$xValue = PHPExcel_Calculation_Functions::flattenSingleValue($xValue);
1609
if (!is_numeric($xValue)) {
1610
return PHPExcel_Calculation_Functions::VALUE();
1611
} elseif (!self::checkTrendArrays($yValues, $xValues)) {
1612
return PHPExcel_Calculation_Functions::VALUE();
1614
$yValueCount = count($yValues);
1615
$xValueCount = count($xValues);
1617
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1618
return PHPExcel_Calculation_Functions::NA();
1619
} elseif ($yValueCount == 1) {
1620
return PHPExcel_Calculation_Functions::DIV0();
1623
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
1624
return $bestFitLinear->getValueOfYForX($xValue);
1631
* Returns the gamma distribution.
1633
* @param float $value Value at which you want to evaluate the distribution
1634
* @param float $a Parameter to the distribution
1635
* @param float $b Parameter to the distribution
1636
* @param boolean $cumulative
1640
public static function GAMMADIST($value, $a, $b, $cumulative)
1642
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
1643
$a = PHPExcel_Calculation_Functions::flattenSingleValue($a);
1644
$b = PHPExcel_Calculation_Functions::flattenSingleValue($b);
1646
if ((is_numeric($value)) && (is_numeric($a)) && (is_numeric($b))) {
1647
if (($value < 0) || ($a <= 0) || ($b <= 0)) {
1648
return PHPExcel_Calculation_Functions::NaN();
1650
if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1652
return self::incompleteGamma($a, $value / $b) / self::gamma($a);
1654
return (1 / (pow($b, $a) * self::gamma($a))) * pow($value, $a-1) * exp(0-($value / $b));
1658
return PHPExcel_Calculation_Functions::VALUE();
1665
* Returns the inverse of the beta distribution.
1667
* @param float $probability Probability at which you want to evaluate the distribution
1668
* @param float $alpha Parameter to the distribution
1669
* @param float $beta Parameter to the distribution
1673
public static function GAMMAINV($probability, $alpha, $beta)
1675
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
1676
$alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
1677
$beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
1679
if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) {
1680
if (($alpha <= 0) || ($beta <= 0) || ($probability < 0) || ($probability > 1)) {
1681
return PHPExcel_Calculation_Functions::NaN();
1685
$xHi = $alpha * $beta * 5;
1692
while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
1693
// Apply Newton-Raphson step
1694
$error = self::GAMMADIST($x, $alpha, $beta, true) - $probability;
1700
$pdf = self::GAMMADIST($x, $alpha, $beta, false);
1701
// Avoid division by zero
1703
$dx = $error / $pdf;
1706
// If the NR fails to converge (which for example may be the
1707
// case if the initial guess is too rough) we apply a bisection
1708
// step to determine a more narrow interval around the root.
1709
if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) {
1710
$xNew = ($xLo + $xHi) / 2;
1715
if ($i == MAX_ITERATIONS) {
1716
return PHPExcel_Calculation_Functions::NA();
1720
return PHPExcel_Calculation_Functions::VALUE();
1727
* Returns the natural logarithm of the gamma function.
1729
* @param float $value
1732
public static function GAMMALN($value)
1734
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
1736
if (is_numeric($value)) {
1738
return PHPExcel_Calculation_Functions::NaN();
1740
return log(self::gamma($value));
1742
return PHPExcel_Calculation_Functions::VALUE();
1749
* Returns the geometric mean of an array or range of positive data. For example, you
1750
* can use GEOMEAN to calculate average growth rate given compound interest with
1754
* GEOMEAN(value1[,value2[, ...]])
1757
* @category Statistical Functions
1758
* @param mixed $arg,... Data values
1761
public static function GEOMEAN()
1763
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
1765
$aMean = PHPExcel_Calculation_MathTrig::PRODUCT($aArgs);
1766
if (is_numeric($aMean) && ($aMean > 0)) {
1767
$aCount = self::COUNT($aArgs) ;
1768
if (self::MIN($aArgs) > 0) {
1769
return pow($aMean, (1 / $aCount));
1772
return PHPExcel_Calculation_Functions::NaN();
1779
* Returns values along a predicted emponential trend
1781
* @param array of mixed Data Series Y
1782
* @param array of mixed Data Series X
1783
* @param array of mixed Values of X for which we want to find Y
1784
* @param boolean A logical value specifying whether to force the intersect to equal 0.
1785
* @return array of float
1787
public static function GROWTH($yValues, $xValues = array(), $newValues = array(), $const = true)
1789
$yValues = PHPExcel_Calculation_Functions::flattenArray($yValues);
1790
$xValues = PHPExcel_Calculation_Functions::flattenArray($xValues);
1791
$newValues = PHPExcel_Calculation_Functions::flattenArray($newValues);
1792
$const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
1794
$bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL, $yValues, $xValues, $const);
1795
if (empty($newValues)) {
1796
$newValues = $bestFitExponential->getXValues();
1799
$returnArray = array();
1800
foreach ($newValues as $xValue) {
1801
$returnArray[0][] = $bestFitExponential->getValueOfYForX($xValue);
1804
return $returnArray;
1811
* Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the
1812
* arithmetic mean of reciprocals.
1815
* HARMEAN(value1[,value2[, ...]])
1818
* @category Statistical Functions
1819
* @param mixed $arg,... Data values
1822
public static function HARMEAN()
1825
$returnValue = PHPExcel_Calculation_Functions::NA();
1827
// Loop through arguments
1828
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
1829
if (self::MIN($aArgs) < 0) {
1830
return PHPExcel_Calculation_Functions::NaN();
1833
foreach ($aArgs as $arg) {
1834
// Is it a numeric value?
1835
if ((is_numeric($arg)) && (!is_string($arg))) {
1837
return PHPExcel_Calculation_Functions::NaN();
1839
if (is_null($returnValue)) {
1840
$returnValue = (1 / $arg);
1842
$returnValue += (1 / $arg);
1850
return 1 / ($returnValue / $aCount);
1852
return $returnValue;
1860
* Returns the hypergeometric distribution. HYPGEOMDIST returns the probability of a given number of
1861
* sample successes, given the sample size, population successes, and population size.
1863
* @param float $sampleSuccesses Number of successes in the sample
1864
* @param float $sampleNumber Size of the sample
1865
* @param float $populationSuccesses Number of successes in the population
1866
* @param float $populationNumber Population size
1870
public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber)
1872
$sampleSuccesses = floor(PHPExcel_Calculation_Functions::flattenSingleValue($sampleSuccesses));
1873
$sampleNumber = floor(PHPExcel_Calculation_Functions::flattenSingleValue($sampleNumber));
1874
$populationSuccesses = floor(PHPExcel_Calculation_Functions::flattenSingleValue($populationSuccesses));
1875
$populationNumber = floor(PHPExcel_Calculation_Functions::flattenSingleValue($populationNumber));
1877
if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) {
1878
if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) {
1879
return PHPExcel_Calculation_Functions::NaN();
1881
if (($sampleNumber <= 0) || ($sampleNumber > $populationNumber)) {
1882
return PHPExcel_Calculation_Functions::NaN();
1884
if (($populationSuccesses <= 0) || ($populationSuccesses > $populationNumber)) {
1885
return PHPExcel_Calculation_Functions::NaN();
1887
return PHPExcel_Calculation_MathTrig::COMBIN($populationSuccesses, $sampleSuccesses) *
1888
PHPExcel_Calculation_MathTrig::COMBIN($populationNumber - $populationSuccesses, $sampleNumber - $sampleSuccesses) /
1889
PHPExcel_Calculation_MathTrig::COMBIN($populationNumber, $sampleNumber);
1891
return PHPExcel_Calculation_Functions::VALUE();
1898
* Calculates the point at which a line will intersect the y-axis by using existing x-values and y-values.
1900
* @param array of mixed Data Series Y
1901
* @param array of mixed Data Series X
1904
public static function INTERCEPT($yValues, $xValues)
1906
if (!self::checkTrendArrays($yValues, $xValues)) {
1907
return PHPExcel_Calculation_Functions::VALUE();
1909
$yValueCount = count($yValues);
1910
$xValueCount = count($xValues);
1912
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1913
return PHPExcel_Calculation_Functions::NA();
1914
} elseif ($yValueCount == 1) {
1915
return PHPExcel_Calculation_Functions::DIV0();
1918
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
1919
return $bestFitLinear->getIntersect();
1926
* Returns the kurtosis of a data set. Kurtosis characterizes the relative peakedness
1927
* or flatness of a distribution compared with the normal distribution. Positive
1928
* kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a
1929
* relatively flat distribution.
1931
* @param array Data Series
1934
public static function KURT()
1936
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
1937
$mean = self::AVERAGE($aArgs);
1938
$stdDev = self::STDEV($aArgs);
1941
$count = $summer = 0;
1942
// Loop through arguments
1943
foreach ($aArgs as $k => $arg) {
1944
if ((is_bool($arg)) &&
1945
(!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
1947
// Is it a numeric value?
1948
if ((is_numeric($arg)) && (!is_string($arg))) {
1949
$summer += pow((($arg - $mean) / $stdDev), 4);
1957
return $summer * ($count * ($count+1) / (($count-1) * ($count-2) * ($count-3))) - (3 * pow($count-1, 2) / (($count-2) * ($count-3)));
1960
return PHPExcel_Calculation_Functions::DIV0();
1967
* Returns the nth largest value in a data set. You can use this function to
1968
* select a value based on its relative standing.
1971
* LARGE(value1[,value2[, ...]],entry)
1974
* @category Statistical Functions
1975
* @param mixed $arg,... Data values
1976
* @param int $entry Position (ordered from the largest) in the array or range of data to return
1980
public static function LARGE()
1982
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
1985
$entry = floor(array_pop($aArgs));
1987
if ((is_numeric($entry)) && (!is_string($entry))) {
1989
foreach ($aArgs as $arg) {
1990
// Is it a numeric value?
1991
if ((is_numeric($arg)) && (!is_string($arg))) {
1995
$count = self::COUNT($mArgs);
1996
$entry = floor(--$entry);
1997
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
1998
return PHPExcel_Calculation_Functions::NaN();
2001
return $mArgs[$entry];
2003
return PHPExcel_Calculation_Functions::VALUE();
2010
* Calculates the statistics for a line by using the "least squares" method to calculate a straight line that best fits your data,
2011
* and then returns an array that describes the line.
2013
* @param array of mixed Data Series Y
2014
* @param array of mixed Data Series X
2015
* @param boolean A logical value specifying whether to force the intersect to equal 0.
2016
* @param boolean A logical value specifying whether to return additional regression statistics.
2019
public static function LINEST($yValues, $xValues = null, $const = true, $stats = false)
2021
$const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
2022
$stats = (is_null($stats)) ? false : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats);
2023
if (is_null($xValues)) {
2024
$xValues = range(1, count(PHPExcel_Calculation_Functions::flattenArray($yValues)));
2027
if (!self::checkTrendArrays($yValues, $xValues)) {
2028
return PHPExcel_Calculation_Functions::VALUE();
2030
$yValueCount = count($yValues);
2031
$xValueCount = count($xValues);
2034
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2035
return PHPExcel_Calculation_Functions::NA();
2036
} elseif ($yValueCount == 1) {
2040
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues, $const);
2044
$bestFitLinear->getSlope(),
2045
$bestFitLinear->getSlopeSE(),
2046
$bestFitLinear->getGoodnessOfFit(),
2047
$bestFitLinear->getF(),
2048
$bestFitLinear->getSSRegression(),
2051
$bestFitLinear->getIntersect(),
2052
$bestFitLinear->getIntersectSE(),
2053
$bestFitLinear->getStdevOfResiduals(),
2054
$bestFitLinear->getDFResiduals(),
2055
$bestFitLinear->getSSResiduals()
2060
$bestFitLinear->getSlope(),
2061
$bestFitLinear->getIntersect()
2070
* Calculates an exponential curve that best fits the X and Y data series,
2071
* and then returns an array that describes the line.
2073
* @param array of mixed Data Series Y
2074
* @param array of mixed Data Series X
2075
* @param boolean A logical value specifying whether to force the intersect to equal 0.
2076
* @param boolean A logical value specifying whether to return additional regression statistics.
2079
public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false)
2081
$const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
2082
$stats = (is_null($stats)) ? false : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats);
2083
if (is_null($xValues)) {
2084
$xValues = range(1, count(PHPExcel_Calculation_Functions::flattenArray($yValues)));
2087
if (!self::checkTrendArrays($yValues, $xValues)) {
2088
return PHPExcel_Calculation_Functions::VALUE();
2090
$yValueCount = count($yValues);
2091
$xValueCount = count($xValues);
2093
foreach ($yValues as $value) {
2094
if ($value <= 0.0) {
2095
return PHPExcel_Calculation_Functions::NaN();
2100
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2101
return PHPExcel_Calculation_Functions::NA();
2102
} elseif ($yValueCount == 1) {
2106
$bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL, $yValues, $xValues, $const);
2110
$bestFitExponential->getSlope(),
2111
$bestFitExponential->getSlopeSE(),
2112
$bestFitExponential->getGoodnessOfFit(),
2113
$bestFitExponential->getF(),
2114
$bestFitExponential->getSSRegression(),
2117
$bestFitExponential->getIntersect(),
2118
$bestFitExponential->getIntersectSE(),
2119
$bestFitExponential->getStdevOfResiduals(),
2120
$bestFitExponential->getDFResiduals(),
2121
$bestFitExponential->getSSResiduals()
2126
$bestFitExponential->getSlope(),
2127
$bestFitExponential->getIntersect()
2136
* Returns the inverse of the normal cumulative distribution
2138
* @param float $probability
2139
* @param float $mean
2140
* @param float $stdDev
2143
* @todo Try implementing P J Acklam's refinement algorithm for greater
2144
* accuracy if I can get my head round the mathematics
2145
* (as described at) http://home.online.no/~pjacklam/notes/invnorm/
2147
public static function LOGINV($probability, $mean, $stdDev)
2149
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
2150
$mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
2151
$stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
2153
if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2154
if (($probability < 0) || ($probability > 1) || ($stdDev <= 0)) {
2155
return PHPExcel_Calculation_Functions::NaN();
2157
return exp($mean + $stdDev * self::NORMSINV($probability));
2159
return PHPExcel_Calculation_Functions::VALUE();
2166
* Returns the cumulative lognormal distribution of x, where ln(x) is normally distributed
2167
* with parameters mean and standard_dev.
2169
* @param float $value
2170
* @param float $mean
2171
* @param float $stdDev
2174
public static function LOGNORMDIST($value, $mean, $stdDev)
2176
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
2177
$mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
2178
$stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
2180
if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2181
if (($value <= 0) || ($stdDev <= 0)) {
2182
return PHPExcel_Calculation_Functions::NaN();
2184
return self::NORMSDIST((log($value) - $mean) / $stdDev);
2186
return PHPExcel_Calculation_Functions::VALUE();
2193
* MAX returns the value of the element of the values passed that has the highest value,
2194
* with negative numbers considered smaller than positive numbers.
2197
* MAX(value1[,value2[, ...]])
2200
* @category Statistical Functions
2201
* @param mixed $arg,... Data values
2204
public static function MAX()
2206
$returnValue = null;
2208
// Loop through arguments
2209
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2210
foreach ($aArgs as $arg) {
2211
// Is it a numeric value?
2212
if ((is_numeric($arg)) && (!is_string($arg))) {
2213
if ((is_null($returnValue)) || ($arg > $returnValue)) {
2214
$returnValue = $arg;
2219
if (is_null($returnValue)) {
2222
return $returnValue;
2229
* Returns the greatest value in a list of arguments, including numbers, text, and logical values
2232
* MAXA(value1[,value2[, ...]])
2235
* @category Statistical Functions
2236
* @param mixed $arg,... Data values
2239
public static function MAXA()
2241
$returnValue = null;
2243
// Loop through arguments
2244
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2245
foreach ($aArgs as $arg) {
2246
// Is it a numeric value?
2247
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
2248
if (is_bool($arg)) {
2249
$arg = (integer) $arg;
2250
} elseif (is_string($arg)) {
2253
if ((is_null($returnValue)) || ($arg > $returnValue)) {
2254
$returnValue = $arg;
2259
if (is_null($returnValue)) {
2262
return $returnValue;
2269
* Counts the maximum value within a range of cells that contain numbers within the list of arguments
2272
* MAXIF(value1[,value2[, ...]],condition)
2275
* @category Mathematical and Trigonometric Functions
2276
* @param mixed $arg,... Data values
2277
* @param string $condition The criteria that defines which cells will be checked.
2280
public static function MAXIF($aArgs, $condition, $sumArgs = array())
2282
$returnValue = null;
2284
$aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
2285
$sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs);
2286
if (empty($sumArgs)) {
2289
$condition = PHPExcel_Calculation_Functions::ifCondition($condition);
2290
// Loop through arguments
2291
foreach ($aArgs as $key => $arg) {
2292
if (!is_numeric($arg)) {
2293
$arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
2295
$testCondition = '='.$arg.$condition;
2296
if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2297
if ((is_null($returnValue)) || ($arg > $returnValue)) {
2298
$returnValue = $arg;
2303
return $returnValue;
2309
* Returns the median of the given numbers. The median is the number in the middle of a set of numbers.
2312
* MEDIAN(value1[,value2[, ...]])
2315
* @category Statistical Functions
2316
* @param mixed $arg,... Data values
2319
public static function MEDIAN()
2321
$returnValue = PHPExcel_Calculation_Functions::NaN();
2324
// Loop through arguments
2325
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2326
foreach ($aArgs as $arg) {
2327
// Is it a numeric value?
2328
if ((is_numeric($arg)) && (!is_string($arg))) {
2333
$mValueCount = count($mArgs);
2334
if ($mValueCount > 0) {
2335
sort($mArgs, SORT_NUMERIC);
2336
$mValueCount = $mValueCount / 2;
2337
if ($mValueCount == floor($mValueCount)) {
2338
$returnValue = ($mArgs[$mValueCount--] + $mArgs[$mValueCount]) / 2;
2340
$mValueCount = floor($mValueCount);
2341
$returnValue = $mArgs[$mValueCount];
2345
return $returnValue;
2352
* MIN returns the value of the element of the values passed that has the smallest value,
2353
* with negative numbers considered smaller than positive numbers.
2356
* MIN(value1[,value2[, ...]])
2359
* @category Statistical Functions
2360
* @param mixed $arg,... Data values
2363
public static function MIN()
2365
$returnValue = null;
2367
// Loop through arguments
2368
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2369
foreach ($aArgs as $arg) {
2370
// Is it a numeric value?
2371
if ((is_numeric($arg)) && (!is_string($arg))) {
2372
if ((is_null($returnValue)) || ($arg < $returnValue)) {
2373
$returnValue = $arg;
2378
if (is_null($returnValue)) {
2381
return $returnValue;
2388
* Returns the smallest value in a list of arguments, including numbers, text, and logical values
2391
* MINA(value1[,value2[, ...]])
2394
* @category Statistical Functions
2395
* @param mixed $arg,... Data values
2398
public static function MINA()
2400
$returnValue = null;
2402
// Loop through arguments
2403
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2404
foreach ($aArgs as $arg) {
2405
// Is it a numeric value?
2406
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
2407
if (is_bool($arg)) {
2408
$arg = (integer) $arg;
2409
} elseif (is_string($arg)) {
2412
if ((is_null($returnValue)) || ($arg < $returnValue)) {
2413
$returnValue = $arg;
2418
if (is_null($returnValue)) {
2421
return $returnValue;
2428
* Returns the minimum value within a range of cells that contain numbers within the list of arguments
2431
* MINIF(value1[,value2[, ...]],condition)
2434
* @category Mathematical and Trigonometric Functions
2435
* @param mixed $arg,... Data values
2436
* @param string $condition The criteria that defines which cells will be checked.
2439
public static function MINIF($aArgs, $condition, $sumArgs = array())
2441
$returnValue = null;
2443
$aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
2444
$sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs);
2445
if (empty($sumArgs)) {
2448
$condition = PHPExcel_Calculation_Functions::ifCondition($condition);
2449
// Loop through arguments
2450
foreach ($aArgs as $key => $arg) {
2451
if (!is_numeric($arg)) {
2452
$arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
2454
$testCondition = '='.$arg.$condition;
2455
if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2456
if ((is_null($returnValue)) || ($arg < $returnValue)) {
2457
$returnValue = $arg;
2462
return $returnValue;
2467
// Special variant of array_count_values that isn't limited to strings and integers,
2468
// but can work with floating point numbers as values
2470
private static function modeCalc($data)
2472
$frequencyArray = array();
2473
foreach ($data as $datum) {
2475
foreach ($frequencyArray as $key => $value) {
2476
if ((string) $value['value'] == (string) $datum) {
2477
++$frequencyArray[$key]['frequency'];
2483
$frequencyArray[] = array(
2490
foreach ($frequencyArray as $key => $value) {
2491
$frequencyList[$key] = $value['frequency'];
2492
$valueList[$key] = $value['value'];
2494
array_multisort($frequencyList, SORT_DESC, $valueList, SORT_ASC, SORT_NUMERIC, $frequencyArray);
2496
if ($frequencyArray[0]['frequency'] == 1) {
2497
return PHPExcel_Calculation_Functions::NA();
2499
return $frequencyArray[0]['value'];
2506
* Returns the most frequently occurring, or repetitive, value in an array or range of data
2509
* MODE(value1[,value2[, ...]])
2512
* @category Statistical Functions
2513
* @param mixed $arg,... Data values
2516
public static function MODE()
2518
$returnValue = PHPExcel_Calculation_Functions::NA();
2520
// Loop through arguments
2521
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2524
foreach ($aArgs as $arg) {
2525
// Is it a numeric value?
2526
if ((is_numeric($arg)) && (!is_string($arg))) {
2531
if (!empty($mArgs)) {
2532
return self::modeCalc($mArgs);
2535
return $returnValue;
2542
* Returns the negative binomial distribution. NEGBINOMDIST returns the probability that
2543
* there will be number_f failures before the number_s-th success, when the constant
2544
* probability of a success is probability_s. This function is similar to the binomial
2545
* distribution, except that the number of successes is fixed, and the number of trials is
2546
* variable. Like the binomial, trials are assumed to be independent.
2548
* @param float $failures Number of Failures
2549
* @param float $successes Threshold number of Successes
2550
* @param float $probability Probability of success on each trial
2554
public static function NEGBINOMDIST($failures, $successes, $probability)
2556
$failures = floor(PHPExcel_Calculation_Functions::flattenSingleValue($failures));
2557
$successes = floor(PHPExcel_Calculation_Functions::flattenSingleValue($successes));
2558
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
2560
if ((is_numeric($failures)) && (is_numeric($successes)) && (is_numeric($probability))) {
2561
if (($failures < 0) || ($successes < 1)) {
2562
return PHPExcel_Calculation_Functions::NaN();
2563
} elseif (($probability < 0) || ($probability > 1)) {
2564
return PHPExcel_Calculation_Functions::NaN();
2566
if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
2567
if (($failures + $successes - 1) <= 0) {
2568
return PHPExcel_Calculation_Functions::NaN();
2571
return (PHPExcel_Calculation_MathTrig::COMBIN($failures + $successes - 1, $successes - 1)) * (pow($probability, $successes)) * (pow(1 - $probability, $failures));
2573
return PHPExcel_Calculation_Functions::VALUE();
2580
* Returns the normal distribution for the specified mean and standard deviation. This
2581
* function has a very wide range of applications in statistics, including hypothesis
2584
* @param float $value
2585
* @param float $mean Mean Value
2586
* @param float $stdDev Standard Deviation
2587
* @param boolean $cumulative
2591
public static function NORMDIST($value, $mean, $stdDev, $cumulative)
2593
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
2594
$mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
2595
$stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
2597
if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2599
return PHPExcel_Calculation_Functions::NaN();
2601
if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
2603
return 0.5 * (1 + PHPExcel_Calculation_Engineering::erfVal(($value - $mean) / ($stdDev * sqrt(2))));
2605
return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean, 2) / (2 * ($stdDev * $stdDev))));
2609
return PHPExcel_Calculation_Functions::VALUE();
2616
* Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
2618
* @param float $value
2619
* @param float $mean Mean Value
2620
* @param float $stdDev Standard Deviation
2624
public static function NORMINV($probability, $mean, $stdDev)
2626
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
2627
$mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
2628
$stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
2630
if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2631
if (($probability < 0) || ($probability > 1)) {
2632
return PHPExcel_Calculation_Functions::NaN();
2635
return PHPExcel_Calculation_Functions::NaN();
2637
return (self::inverseNcdf($probability) * $stdDev) + $mean;
2639
return PHPExcel_Calculation_Functions::VALUE();
2646
* Returns the standard normal cumulative distribution function. The distribution has
2647
* a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
2648
* table of standard normal curve areas.
2650
* @param float $value
2653
public static function NORMSDIST($value)
2655
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
2657
return self::NORMDIST($value, 0, 1, true);
2664
* Returns the inverse of the standard normal cumulative distribution
2666
* @param float $value
2669
public static function NORMSINV($value)
2671
return self::NORMINV($value, 0, 1);
2678
* Returns the nth percentile of values in a range..
2681
* PERCENTILE(value1[,value2[, ...]],entry)
2684
* @category Statistical Functions
2685
* @param mixed $arg,... Data values
2686
* @param float $entry Percentile value in the range 0..1, inclusive.
2689
public static function PERCENTILE()
2691
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2694
$entry = array_pop($aArgs);
2696
if ((is_numeric($entry)) && (!is_string($entry))) {
2697
if (($entry < 0) || ($entry > 1)) {
2698
return PHPExcel_Calculation_Functions::NaN();
2701
foreach ($aArgs as $arg) {
2702
// Is it a numeric value?
2703
if ((is_numeric($arg)) && (!is_string($arg))) {
2707
$mValueCount = count($mArgs);
2708
if ($mValueCount > 0) {
2710
$count = self::COUNT($mArgs);
2711
$index = $entry * ($count-1);
2712
$iBase = floor($index);
2713
if ($index == $iBase) {
2714
return $mArgs[$index];
2716
$iNext = $iBase + 1;
2717
$iProportion = $index - $iBase;
2718
return $mArgs[$iBase] + (($mArgs[$iNext] - $mArgs[$iBase]) * $iProportion) ;
2722
return PHPExcel_Calculation_Functions::VALUE();
2729
* Returns the rank of a value in a data set as a percentage of the data set.
2731
* @param array of number An array of, or a reference to, a list of numbers.
2732
* @param number The number whose rank you want to find.
2733
* @param number The number of significant digits for the returned percentage value.
2736
public static function PERCENTRANK($valueSet, $value, $significance = 3)
2738
$valueSet = PHPExcel_Calculation_Functions::flattenArray($valueSet);
2739
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
2740
$significance = (is_null($significance)) ? 3 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($significance);
2742
foreach ($valueSet as $key => $valueEntry) {
2743
if (!is_numeric($valueEntry)) {
2744
unset($valueSet[$key]);
2747
sort($valueSet, SORT_NUMERIC);
2748
$valueCount = count($valueSet);
2749
if ($valueCount == 0) {
2750
return PHPExcel_Calculation_Functions::NaN();
2753
$valueAdjustor = $valueCount - 1;
2754
if (($value < $valueSet[0]) || ($value > $valueSet[$valueAdjustor])) {
2755
return PHPExcel_Calculation_Functions::NA();
2758
$pos = array_search($value, $valueSet);
2759
if ($pos === false) {
2761
$testValue = $valueSet[0];
2762
while ($testValue < $value) {
2763
$testValue = $valueSet[++$pos];
2766
$pos += (($value - $valueSet[$pos]) / ($testValue - $valueSet[$pos]));
2769
return round($pos / $valueAdjustor, $significance);
2776
* Returns the number of permutations for a given number of objects that can be
2777
* selected from number objects. A permutation is any set or subset of objects or
2778
* events where internal order is significant. Permutations are different from
2779
* combinations, for which the internal order is not significant. Use this function
2780
* for lottery-style probability calculations.
2782
* @param int $numObjs Number of different objects
2783
* @param int $numInSet Number of objects in each permutation
2784
* @return int Number of permutations
2786
public static function PERMUT($numObjs, $numInSet)
2788
$numObjs = PHPExcel_Calculation_Functions::flattenSingleValue($numObjs);
2789
$numInSet = PHPExcel_Calculation_Functions::flattenSingleValue($numInSet);
2791
if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
2792
$numInSet = floor($numInSet);
2793
if ($numObjs < $numInSet) {
2794
return PHPExcel_Calculation_Functions::NaN();
2796
return round(PHPExcel_Calculation_MathTrig::FACT($numObjs) / PHPExcel_Calculation_MathTrig::FACT($numObjs - $numInSet));
2798
return PHPExcel_Calculation_Functions::VALUE();
2805
* Returns the Poisson distribution. A common application of the Poisson distribution
2806
* is predicting the number of events over a specific time, such as the number of
2807
* cars arriving at a toll plaza in 1 minute.
2809
* @param float $value
2810
* @param float $mean Mean Value
2811
* @param boolean $cumulative
2815
public static function POISSON($value, $mean, $cumulative)
2817
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
2818
$mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
2820
if ((is_numeric($value)) && (is_numeric($mean))) {
2821
if (($value < 0) || ($mean <= 0)) {
2822
return PHPExcel_Calculation_Functions::NaN();
2824
if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
2827
for ($i = 0; $i <= floor($value); ++$i) {
2828
$summer += pow($mean, $i) / PHPExcel_Calculation_MathTrig::FACT($i);
2830
return exp(0-$mean) * $summer;
2832
return (exp(0-$mean) * pow($mean, $value)) / PHPExcel_Calculation_MathTrig::FACT($value);
2836
return PHPExcel_Calculation_Functions::VALUE();
2843
* Returns the quartile of a data set.
2846
* QUARTILE(value1[,value2[, ...]],entry)
2849
* @category Statistical Functions
2850
* @param mixed $arg,... Data values
2851
* @param int $entry Quartile value in the range 1..3, inclusive.
2854
public static function QUARTILE()
2856
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
2859
$entry = floor(array_pop($aArgs));
2861
if ((is_numeric($entry)) && (!is_string($entry))) {
2863
if (($entry < 0) || ($entry > 1)) {
2864
return PHPExcel_Calculation_Functions::NaN();
2866
return self::PERCENTILE($aArgs, $entry);
2868
return PHPExcel_Calculation_Functions::VALUE();
2875
* Returns the rank of a number in a list of numbers.
2877
* @param number The number whose rank you want to find.
2878
* @param array of number An array of, or a reference to, a list of numbers.
2879
* @param mixed Order to sort the values in the value set
2882
public static function RANK($value, $valueSet, $order = 0)
2884
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
2885
$valueSet = PHPExcel_Calculation_Functions::flattenArray($valueSet);
2886
$order = (is_null($order)) ? 0 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($order);
2888
foreach ($valueSet as $key => $valueEntry) {
2889
if (!is_numeric($valueEntry)) {
2890
unset($valueSet[$key]);
2895
rsort($valueSet, SORT_NUMERIC);
2897
sort($valueSet, SORT_NUMERIC);
2899
$pos = array_search($value, $valueSet);
2900
if ($pos === false) {
2901
return PHPExcel_Calculation_Functions::NA();
2911
* Returns the square of the Pearson product moment correlation coefficient through data points in known_y's and known_x's.
2913
* @param array of mixed Data Series Y
2914
* @param array of mixed Data Series X
2917
public static function RSQ($yValues, $xValues)
2919
if (!self::checkTrendArrays($yValues, $xValues)) {
2920
return PHPExcel_Calculation_Functions::VALUE();
2922
$yValueCount = count($yValues);
2923
$xValueCount = count($xValues);
2925
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2926
return PHPExcel_Calculation_Functions::NA();
2927
} elseif ($yValueCount == 1) {
2928
return PHPExcel_Calculation_Functions::DIV0();
2931
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
2932
return $bestFitLinear->getGoodnessOfFit();
2939
* Returns the skewness of a distribution. Skewness characterizes the degree of asymmetry
2940
* of a distribution around its mean. Positive skewness indicates a distribution with an
2941
* asymmetric tail extending toward more positive values. Negative skewness indicates a
2942
* distribution with an asymmetric tail extending toward more negative values.
2944
* @param array Data Series
2947
public static function SKEW()
2949
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
2950
$mean = self::AVERAGE($aArgs);
2951
$stdDev = self::STDEV($aArgs);
2953
$count = $summer = 0;
2954
// Loop through arguments
2955
foreach ($aArgs as $k => $arg) {
2956
if ((is_bool($arg)) &&
2957
(!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
2959
// Is it a numeric value?
2960
if ((is_numeric($arg)) && (!is_string($arg))) {
2961
$summer += pow((($arg - $mean) / $stdDev), 3);
2968
return $summer * ($count / (($count-1) * ($count-2)));
2970
return PHPExcel_Calculation_Functions::DIV0();
2977
* Returns the slope of the linear regression line through data points in known_y's and known_x's.
2979
* @param array of mixed Data Series Y
2980
* @param array of mixed Data Series X
2983
public static function SLOPE($yValues, $xValues)
2985
if (!self::checkTrendArrays($yValues, $xValues)) {
2986
return PHPExcel_Calculation_Functions::VALUE();
2988
$yValueCount = count($yValues);
2989
$xValueCount = count($xValues);
2991
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2992
return PHPExcel_Calculation_Functions::NA();
2993
} elseif ($yValueCount == 1) {
2994
return PHPExcel_Calculation_Functions::DIV0();
2997
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
2998
return $bestFitLinear->getSlope();
3005
* Returns the nth smallest value in a data set. You can use this function to
3006
* select a value based on its relative standing.
3009
* SMALL(value1[,value2[, ...]],entry)
3012
* @category Statistical Functions
3013
* @param mixed $arg,... Data values
3014
* @param int $entry Position (ordered from the smallest) in the array or range of data to return
3017
public static function SMALL()
3019
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
3022
$entry = array_pop($aArgs);
3024
if ((is_numeric($entry)) && (!is_string($entry))) {
3026
foreach ($aArgs as $arg) {
3027
// Is it a numeric value?
3028
if ((is_numeric($arg)) && (!is_string($arg))) {
3032
$count = self::COUNT($mArgs);
3033
$entry = floor(--$entry);
3034
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
3035
return PHPExcel_Calculation_Functions::NaN();
3038
return $mArgs[$entry];
3040
return PHPExcel_Calculation_Functions::VALUE();
3047
* Returns a normalized value from a distribution characterized by mean and standard_dev.
3049
* @param float $value Value to normalize
3050
* @param float $mean Mean Value
3051
* @param float $stdDev Standard Deviation
3052
* @return float Standardized value
3054
public static function STANDARDIZE($value, $mean, $stdDev)
3056
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
3057
$mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
3058
$stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
3060
if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
3062
return PHPExcel_Calculation_Functions::NaN();
3064
return ($value - $mean) / $stdDev ;
3066
return PHPExcel_Calculation_Functions::VALUE();
3073
* Estimates standard deviation based on a sample. The standard deviation is a measure of how
3074
* widely values are dispersed from the average value (the mean).
3077
* STDEV(value1[,value2[, ...]])
3080
* @category Statistical Functions
3081
* @param mixed $arg,... Data values
3084
public static function STDEV()
3086
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
3089
$returnValue = null;
3091
$aMean = self::AVERAGE($aArgs);
3092
if (!is_null($aMean)) {
3094
foreach ($aArgs as $k => $arg) {
3095
if ((is_bool($arg)) &&
3096
((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
3097
$arg = (integer) $arg;
3099
// Is it a numeric value?
3100
if ((is_numeric($arg)) && (!is_string($arg))) {
3101
if (is_null($returnValue)) {
3102
$returnValue = pow(($arg - $aMean), 2);
3104
$returnValue += pow(($arg - $aMean), 2);
3111
if (($aCount > 0) && ($returnValue >= 0)) {
3112
return sqrt($returnValue / $aCount);
3115
return PHPExcel_Calculation_Functions::DIV0();
3122
* Estimates standard deviation based on a sample, including numbers, text, and logical values
3125
* STDEVA(value1[,value2[, ...]])
3128
* @category Statistical Functions
3129
* @param mixed $arg,... Data values
3132
public static function STDEVA()
3134
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
3136
$returnValue = null;
3138
$aMean = self::AVERAGEA($aArgs);
3139
if (!is_null($aMean)) {
3141
foreach ($aArgs as $k => $arg) {
3142
if ((is_bool($arg)) &&
3143
(!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
3145
// Is it a numeric value?
3146
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3147
if (is_bool($arg)) {
3148
$arg = (integer) $arg;
3149
} elseif (is_string($arg)) {
3152
if (is_null($returnValue)) {
3153
$returnValue = pow(($arg - $aMean), 2);
3155
$returnValue += pow(($arg - $aMean), 2);
3162
if (($aCount > 0) && ($returnValue >= 0)) {
3163
return sqrt($returnValue / $aCount);
3166
return PHPExcel_Calculation_Functions::DIV0();
3173
* Calculates standard deviation based on the entire population
3176
* STDEVP(value1[,value2[, ...]])
3179
* @category Statistical Functions
3180
* @param mixed $arg,... Data values
3183
public static function STDEVP()
3185
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
3187
$returnValue = null;
3189
$aMean = self::AVERAGE($aArgs);
3190
if (!is_null($aMean)) {
3192
foreach ($aArgs as $k => $arg) {
3193
if ((is_bool($arg)) &&
3194
((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
3195
$arg = (integer) $arg;
3197
// Is it a numeric value?
3198
if ((is_numeric($arg)) && (!is_string($arg))) {
3199
if (is_null($returnValue)) {
3200
$returnValue = pow(($arg - $aMean), 2);
3202
$returnValue += pow(($arg - $aMean), 2);
3208
if (($aCount > 0) && ($returnValue >= 0)) {
3209
return sqrt($returnValue / $aCount);
3212
return PHPExcel_Calculation_Functions::DIV0();
3219
* Calculates standard deviation based on the entire population, including numbers, text, and logical values
3222
* STDEVPA(value1[,value2[, ...]])
3225
* @category Statistical Functions
3226
* @param mixed $arg,... Data values
3229
public static function STDEVPA()
3231
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
3233
$returnValue = null;
3235
$aMean = self::AVERAGEA($aArgs);
3236
if (!is_null($aMean)) {
3238
foreach ($aArgs as $k => $arg) {
3239
if ((is_bool($arg)) &&
3240
(!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
3242
// Is it a numeric value?
3243
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3244
if (is_bool($arg)) {
3245
$arg = (integer) $arg;
3246
} elseif (is_string($arg)) {
3249
if (is_null($returnValue)) {
3250
$returnValue = pow(($arg - $aMean), 2);
3252
$returnValue += pow(($arg - $aMean), 2);
3259
if (($aCount > 0) && ($returnValue >= 0)) {
3260
return sqrt($returnValue / $aCount);
3263
return PHPExcel_Calculation_Functions::DIV0();
3270
* Returns the standard error of the predicted y-value for each x in the regression.
3272
* @param array of mixed Data Series Y
3273
* @param array of mixed Data Series X
3276
public static function STEYX($yValues, $xValues)
3278
if (!self::checkTrendArrays($yValues, $xValues)) {
3279
return PHPExcel_Calculation_Functions::VALUE();
3281
$yValueCount = count($yValues);
3282
$xValueCount = count($xValues);
3284
if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
3285
return PHPExcel_Calculation_Functions::NA();
3286
} elseif ($yValueCount == 1) {
3287
return PHPExcel_Calculation_Functions::DIV0();
3290
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
3291
return $bestFitLinear->getStdevOfResiduals();
3298
* Returns the probability of Student's T distribution.
3300
* @param float $value Value for the function
3301
* @param float $degrees degrees of freedom
3302
* @param float $tails number of tails (1 or 2)
3305
public static function TDIST($value, $degrees, $tails)
3307
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
3308
$degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
3309
$tails = floor(PHPExcel_Calculation_Functions::flattenSingleValue($tails));
3311
if ((is_numeric($value)) && (is_numeric($degrees)) && (is_numeric($tails))) {
3312
if (($value < 0) || ($degrees < 1) || ($tails < 1) || ($tails > 2)) {
3313
return PHPExcel_Calculation_Functions::NaN();
3315
// tdist, which finds the probability that corresponds to a given value
3316
// of t with k degrees of freedom. This algorithm is translated from a
3317
// pascal function on p81 of "Statistical Computing in Pascal" by D
3318
// Cooke, A H Craven & G M Clark (1985: Edward Arnold (Pubs.) Ltd:
3319
// London). The above Pascal algorithm is itself a translation of the
3320
// fortran algoritm "AS 3" by B E Cooper of the Atlas Computer
3321
// Laboratory as reported in (among other places) "Applied Statistics
3322
// Algorithms", editied by P Griffiths and I D Hill (1985; Ellis
3323
// Horwood Ltd.; W. Sussex, England).
3325
$ttheta = atan2($value, sqrt($tterm));
3330
if (($degrees % 2) == 1) {
3339
while ($ti < $degrees) {
3340
$tterm *= $tc * $tc * ($ti - 1) / $ti;
3345
if (($degrees % 2) == 1) {
3346
$tsum = M_2DIVPI * ($tsum + $ttheta);
3348
$tValue = 0.5 * (1 + $tsum);
3350
return 1 - abs($tValue);
3352
return 1 - abs((1 - $tValue) - $tValue);
3355
return PHPExcel_Calculation_Functions::VALUE();
3362
* Returns the one-tailed probability of the chi-squared distribution.
3364
* @param float $probability Probability for the function
3365
* @param float $degrees degrees of freedom
3368
public static function TINV($probability, $degrees)
3370
$probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
3371
$degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
3373
if ((is_numeric($probability)) && (is_numeric($degrees))) {
3381
while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
3382
// Apply Newton-Raphson step
3383
$result = self::TDIST($x, $degrees, 2);
3384
$error = $result - $probability;
3385
if ($error == 0.0) {
3387
} elseif ($error < 0.0) {
3392
// Avoid division by zero
3393
if ($result != 0.0) {
3394
$dx = $error / $result;
3397
// If the NR fails to converge (which for example may be the
3398
// case if the initial guess is too rough) we apply a bisection
3399
// step to determine a more narrow interval around the root.
3400
if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
3401
$xNew = ($xLo + $xHi) / 2;
3406
if ($i == MAX_ITERATIONS) {
3407
return PHPExcel_Calculation_Functions::NA();
3409
return round($x, 12);
3411
return PHPExcel_Calculation_Functions::VALUE();
3418
* Returns values along a linear trend
3420
* @param array of mixed Data Series Y
3421
* @param array of mixed Data Series X
3422
* @param array of mixed Values of X for which we want to find Y
3423
* @param boolean A logical value specifying whether to force the intersect to equal 0.
3424
* @return array of float
3426
public static function TREND($yValues, $xValues = array(), $newValues = array(), $const = true)
3428
$yValues = PHPExcel_Calculation_Functions::flattenArray($yValues);
3429
$xValues = PHPExcel_Calculation_Functions::flattenArray($xValues);
3430
$newValues = PHPExcel_Calculation_Functions::flattenArray($newValues);
3431
$const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
3433
$bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues, $const);
3434
if (empty($newValues)) {
3435
$newValues = $bestFitLinear->getXValues();
3438
$returnArray = array();
3439
foreach ($newValues as $xValue) {
3440
$returnArray[0][] = $bestFitLinear->getValueOfYForX($xValue);
3443
return $returnArray;
3450
* Returns the mean of the interior of a data set. TRIMMEAN calculates the mean
3451
* taken by excluding a percentage of data points from the top and bottom tails
3455
* TRIMEAN(value1[,value2[, ...]], $discard)
3458
* @category Statistical Functions
3459
* @param mixed $arg,... Data values
3460
* @param float $discard Percentage to discard
3463
public static function TRIMMEAN()
3465
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
3468
$percent = array_pop($aArgs);
3470
if ((is_numeric($percent)) && (!is_string($percent))) {
3471
if (($percent < 0) || ($percent > 1)) {
3472
return PHPExcel_Calculation_Functions::NaN();
3475
foreach ($aArgs as $arg) {
3476
// Is it a numeric value?
3477
if ((is_numeric($arg)) && (!is_string($arg))) {
3481
$discard = floor(self::COUNT($mArgs) * $percent / 2);
3483
for ($i=0; $i < $discard; ++$i) {
3485
array_shift($mArgs);
3487
return self::AVERAGE($mArgs);
3489
return PHPExcel_Calculation_Functions::VALUE();
3496
* Estimates variance based on a sample.
3499
* VAR(value1[,value2[, ...]])
3502
* @category Statistical Functions
3503
* @param mixed $arg,... Data values
3506
public static function VARFunc()
3508
$returnValue = PHPExcel_Calculation_Functions::DIV0();
3510
$summerA = $summerB = 0;
3512
// Loop through arguments
3513
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
3515
foreach ($aArgs as $arg) {
3516
if (is_bool($arg)) {
3517
$arg = (integer) $arg;
3519
// Is it a numeric value?
3520
if ((is_numeric($arg)) && (!is_string($arg))) {
3521
$summerA += ($arg * $arg);
3528
$summerA *= $aCount;
3529
$summerB *= $summerB;
3530
$returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
3532
return $returnValue;
3539
* Estimates variance based on a sample, including numbers, text, and logical values
3542
* VARA(value1[,value2[, ...]])
3545
* @category Statistical Functions
3546
* @param mixed $arg,... Data values
3549
public static function VARA()
3551
$returnValue = PHPExcel_Calculation_Functions::DIV0();
3553
$summerA = $summerB = 0;
3555
// Loop through arguments
3556
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
3558
foreach ($aArgs as $k => $arg) {
3559
if ((is_string($arg)) &&
3560
(PHPExcel_Calculation_Functions::isValue($k))) {
3561
return PHPExcel_Calculation_Functions::VALUE();
3562
} elseif ((is_string($arg)) &&
3563
(!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
3565
// Is it a numeric value?
3566
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3567
if (is_bool($arg)) {
3568
$arg = (integer) $arg;
3569
} elseif (is_string($arg)) {
3572
$summerA += ($arg * $arg);
3580
$summerA *= $aCount;
3581
$summerB *= $summerB;
3582
$returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
3584
return $returnValue;
3591
* Calculates variance based on the entire population
3594
* VARP(value1[,value2[, ...]])
3597
* @category Statistical Functions
3598
* @param mixed $arg,... Data values
3601
public static function VARP()
3604
$returnValue = PHPExcel_Calculation_Functions::DIV0();
3606
$summerA = $summerB = 0;
3608
// Loop through arguments
3609
$aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
3611
foreach ($aArgs as $arg) {
3612
if (is_bool($arg)) {
3613
$arg = (integer) $arg;
3615
// Is it a numeric value?
3616
if ((is_numeric($arg)) && (!is_string($arg))) {
3617
$summerA += ($arg * $arg);
3624
$summerA *= $aCount;
3625
$summerB *= $summerB;
3626
$returnValue = ($summerA - $summerB) / ($aCount * $aCount);
3628
return $returnValue;
3635
* Calculates variance based on the entire population, including numbers, text, and logical values
3638
* VARPA(value1[,value2[, ...]])
3641
* @category Statistical Functions
3642
* @param mixed $arg,... Data values
3645
public static function VARPA()
3647
$returnValue = PHPExcel_Calculation_Functions::DIV0();
3649
$summerA = $summerB = 0;
3651
// Loop through arguments
3652
$aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
3654
foreach ($aArgs as $k => $arg) {
3655
if ((is_string($arg)) &&
3656
(PHPExcel_Calculation_Functions::isValue($k))) {
3657
return PHPExcel_Calculation_Functions::VALUE();
3658
} elseif ((is_string($arg)) &&
3659
(!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
3661
// Is it a numeric value?
3662
if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3663
if (is_bool($arg)) {
3664
$arg = (integer) $arg;
3665
} elseif (is_string($arg)) {
3668
$summerA += ($arg * $arg);
3676
$summerA *= $aCount;
3677
$summerB *= $summerB;
3678
$returnValue = ($summerA - $summerB) / ($aCount * $aCount);
3680
return $returnValue;
3687
* Returns the Weibull distribution. Use this distribution in reliability
3688
* analysis, such as calculating a device's mean time to failure.
3690
* @param float $value
3691
* @param float $alpha Alpha Parameter
3692
* @param float $beta Beta Parameter
3693
* @param boolean $cumulative
3697
public static function WEIBULL($value, $alpha, $beta, $cumulative)
3699
$value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
3700
$alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
3701
$beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
3703
if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta))) {
3704
if (($value < 0) || ($alpha <= 0) || ($beta <= 0)) {
3705
return PHPExcel_Calculation_Functions::NaN();
3707
if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
3709
return 1 - exp(0 - pow($value / $beta, $alpha));
3711
return ($alpha / pow($beta, $alpha)) * pow($value, $alpha - 1) * exp(0 - pow($value / $beta, $alpha));
3715
return PHPExcel_Calculation_Functions::VALUE();
3722
* Returns the Weibull distribution. Use this distribution in reliability
3723
* analysis, such as calculating a device's mean time to failure.
3725
* @param float $dataSet
3726
* @param float $m0 Alpha Parameter
3727
* @param float $sigma Beta Parameter
3728
* @param boolean $cumulative
3732
public static function ZTEST($dataSet, $m0, $sigma = null)
3734
$dataSet = PHPExcel_Calculation_Functions::flattenArrayIndexed($dataSet);
3735
$m0 = PHPExcel_Calculation_Functions::flattenSingleValue($m0);
3736
$sigma = PHPExcel_Calculation_Functions::flattenSingleValue($sigma);
3738
if (is_null($sigma)) {
3739
$sigma = self::STDEV($dataSet);
3741
$n = count($dataSet);
3743
return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0) / ($sigma / SQRT($n)));