Skip to content

Commit 9683e5b

Browse files
author
Mark Baker
authored
More unit tests for statistical functions, including a bugfix to LARGE() (#1601)
* More unit tests for statistical functions, including a bugfix to LARGE() that was identified in testing
1 parent a203c3a commit 9683e5b

File tree

23 files changed

+478
-28
lines changed

23 files changed

+478
-28
lines changed

src/PhpSpreadsheet/Calculation/Database.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ public static function DSUM($database, $field, $criteria)
552552
* the column label in which you specify a condition for the
553553
* column.
554554
*
555-
* @return float
555+
* @return float|string (string if result is an error)
556556
*/
557557
public static function DVAR($database, $field, $criteria)
558558
{
@@ -591,7 +591,7 @@ public static function DVAR($database, $field, $criteria)
591591
* the column label in which you specify a condition for the
592592
* column.
593593
*
594-
* @return float
594+
* @return float|string (string if result is an error)
595595
*/
596596
public static function DVARP($database, $field, $criteria)
597597
{

src/PhpSpreadsheet/Calculation/LookupRef.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public static function COLUMN($cellAddress = null)
126126
*
127127
* @param null|array|string $cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns
128128
*
129-
* @return int The number of columns in cellAddress
129+
* @return int|string The number of columns in cellAddress, or a string if arguments are invalid
130130
*/
131131
public static function COLUMNS($cellAddress = null)
132132
{
@@ -160,7 +160,7 @@ public static function COLUMNS($cellAddress = null)
160160
*
161161
* @param null|array|string $cellAddress A reference to a range of cells for which you want the row numbers
162162
*
163-
* @return int or array of integer
163+
* @return int|mixed[]|string
164164
*/
165165
public static function ROW($cellAddress = null)
166166
{
@@ -203,7 +203,7 @@ public static function ROW($cellAddress = null)
203203
*
204204
* @param null|array|string $cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows
205205
*
206-
* @return int The number of rows in cellAddress
206+
* @return int|string The number of rows in cellAddress, or a string if arguments are invalid
207207
*/
208208
public static function ROWS($cellAddress = null)
209209
{

src/PhpSpreadsheet/Calculation/MathTrig.php

+7-6
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ public static function MROUND($number, $multiple)
871871
*
872872
* Returns the ratio of the factorial of a sum of values to the product of factorials.
873873
*
874-
* @param array of mixed Data Series
874+
* @param mixed[] $args An array of mixed values for the Data Series
875875
*
876876
* @return float|string The result, or a string containing an error
877877
*/
@@ -1149,7 +1149,7 @@ public static function ROUNDDOWN($number, $digits)
11491149
*
11501150
* Returns the sum of a power series
11511151
*
1152-
* @param array of mixed Data Series
1152+
* @param mixed[] $args An array of mixed values for the Data Series
11531153
*
11541154
* @return float|string The result, or a string containing an error
11551155
*/
@@ -1273,21 +1273,22 @@ function ($index) use ($cellReference) {
12731273
*
12741274
* Returns a subtotal in a list or database.
12751275
*
1276-
* @param int the number 1 to 11 that specifies which function to
1276+
* @param int $functionType
1277+
* A number 1 to 11 that specifies which function to
12771278
* use in calculating subtotals within a range
12781279
* list
12791280
* Numbers 101 to 111 shadow the functions of 1 to 11
12801281
* but ignore any values in the range that are
12811282
* in hidden rows or columns
1282-
* @param array of mixed Data Series
1283+
* @param mixed[] $args A mixed data series of values
12831284
*
12841285
* @return float|string
12851286
*/
1286-
public static function SUBTOTAL(...$args)
1287+
public static function SUBTOTAL($functionType, ...$args)
12871288
{
12881289
$cellReference = array_pop($args);
12891290
$aArgs = Functions::flattenArrayIndexed($args);
1290-
$subtotal = array_shift($aArgs);
1291+
$subtotal = Functions::flattenSingleValue($functionType);
12911292

12921293
// Calculate
12931294
if ((is_numeric($subtotal)) && (!is_string($subtotal))) {

src/PhpSpreadsheet/Calculation/Statistical.php

+16-15
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ public static function DEVSQ(...$args)
14451445
return $returnValue;
14461446
}
14471447

1448-
return self::NA();
1448+
return Functions::NA();
14491449
}
14501450

14511451
/**
@@ -1701,7 +1701,6 @@ public static function GAMMAINV($probability, $alpha, $beta)
17011701
$xHi = $alpha * $beta * 5;
17021702

17031703
$x = $xNew = 1;
1704-
$error = $pdf = 0;
17051704
$dx = 1024;
17061705
$i = 0;
17071706

@@ -2019,11 +2018,12 @@ public static function KURT(...$args)
20192018
public static function LARGE(...$args)
20202019
{
20212020
$aArgs = Functions::flattenArray($args);
2022-
2023-
// Calculate
2024-
$entry = floor(array_pop($aArgs));
2021+
$entry = array_pop($aArgs);
20252022

20262023
if ((is_numeric($entry)) && (!is_string($entry))) {
2024+
$entry = (int) floor($entry);
2025+
2026+
// Calculate
20272027
$mArgs = [];
20282028
foreach ($aArgs as $arg) {
20292029
// Is it a numeric value?
@@ -2032,7 +2032,7 @@ public static function LARGE(...$args)
20322032
}
20332033
}
20342034
$count = self::COUNT($mArgs);
2035-
$entry = floor(--$entry);
2035+
--$entry;
20362036
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
20372037
return Functions::NAN();
20382038
}
@@ -2873,7 +2873,7 @@ public static function PERCENTILE(...$args)
28732873
* @param int $value the number whose rank you want to find
28742874
* @param int $significance the number of significant digits for the returned percentage value
28752875
*
2876-
* @return float
2876+
* @return float|string (string if result is an error)
28772877
*/
28782878
public static function PERCENTRANK($valueSet, $value, $significance = 3)
28792879
{
@@ -3169,6 +3169,8 @@ public static function SMALL(...$args)
31693169
$entry = array_pop($aArgs);
31703170

31713171
if ((is_numeric($entry)) && (!is_string($entry))) {
3172+
$entry = (int) floor($entry);
3173+
31723174
$mArgs = [];
31733175
foreach ($aArgs as $arg) {
31743176
// Is it a numeric value?
@@ -3177,7 +3179,7 @@ public static function SMALL(...$args)
31773179
}
31783180
}
31793181
$count = self::COUNT($mArgs);
3180-
$entry = floor(--$entry);
3182+
--$entry;
31813183
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
31823184
return Functions::NAN();
31833185
}
@@ -3481,7 +3483,6 @@ public static function TDIST($value, $degrees, $tails)
34813483
$ttheta = atan2($value, sqrt($tterm));
34823484
$tc = cos($ttheta);
34833485
$ts = sin($ttheta);
3484-
$tsum = 0;
34853486

34863487
if (($degrees % 2) == 1) {
34873488
$ti = 3;
@@ -3657,7 +3658,7 @@ public static function TRIMMEAN(...$args)
36573658
*
36583659
* @param mixed ...$args Data values
36593660
*
3660-
* @return float
3661+
* @return float|string (string if result is an error)
36613662
*/
36623663
public static function VARFunc(...$args)
36633664
{
@@ -3699,7 +3700,7 @@ public static function VARFunc(...$args)
36993700
*
37003701
* @param mixed ...$args Data values
37013702
*
3702-
* @return float
3703+
* @return float|string (string if result is an error)
37033704
*/
37043705
public static function VARA(...$args)
37053706
{
@@ -3754,7 +3755,7 @@ public static function VARA(...$args)
37543755
*
37553756
* @param mixed ...$args Data values
37563757
*
3757-
* @return float
3758+
* @return float|string (string if result is an error)
37583759
*/
37593760
public static function VARP(...$args)
37603761
{
@@ -3797,7 +3798,7 @@ public static function VARP(...$args)
37973798
*
37983799
* @param mixed ...$args Data values
37993800
*
3800-
* @return float
3801+
* @return float|string (string if result is an error)
38013802
*/
38023803
public static function VARPA(...$args)
38033804
{
@@ -3853,7 +3854,7 @@ public static function VARPA(...$args)
38533854
* @param float $beta Beta Parameter
38543855
* @param bool $cumulative
38553856
*
3856-
* @return float
3857+
* @return float|string (string if result is an error)
38573858
*/
38583859
public static function WEIBULL($value, $alpha, $beta, $cumulative)
38593860
{
@@ -3887,7 +3888,7 @@ public static function WEIBULL($value, $alpha, $beta, $cumulative)
38873888
* @param float $m0 Alpha Parameter
38883889
* @param float $sigma Beta Parameter
38893890
*
3890-
* @return float|string
3891+
* @return float|string (string if result is an error)
38913892
*/
38923893
public static function ZTEST($dataSet, $m0, $sigma = null)
38933894
{

src/PhpSpreadsheet/Calculation/TextData.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PhpOffice\PhpSpreadsheet\Calculation;
44

5+
use DateTimeInterface;
56
use PhpOffice\PhpSpreadsheet\Shared\Date;
67
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
78
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
@@ -98,7 +99,7 @@ private static function convertBooleanValue($value)
9899
*
99100
* @param string $characters Value
100101
*
101-
* @return int
102+
* @return int|string A string if arguments are invalid
102103
*/
103104
public static function ASCIICODE($characters)
104105
{
@@ -543,7 +544,7 @@ public static function TEXTFORMAT($value, $format)
543544
*
544545
* @param mixed $value Value to check
545546
*
546-
* @return bool
547+
* @return DateTimeInterface|float|int|string A string if arguments are invalid
547548
*/
548549
public static function VALUE($value = '')
549550
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
4+
5+
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class LargeTest extends TestCase
9+
{
10+
/**
11+
* @dataProvider providerLARGE
12+
*
13+
* @param mixed $expectedResult
14+
* @param mixed $values
15+
* @param mixed $position
16+
*/
17+
public function testLARGE($expectedResult, $values, $position): void
18+
{
19+
$result = Statistical::LARGE($values, $position);
20+
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
21+
}
22+
23+
public function providerLARGE()
24+
{
25+
return require 'tests/data/Calculation/Statistical/LARGE.php';
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
4+
5+
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class LinEstTest extends TestCase
9+
{
10+
/**
11+
* @dataProvider providerLINEST
12+
*
13+
* @param mixed $expectedResult
14+
* @param mixed $xValues
15+
* @param mixed $yValues
16+
* @param mixed $const
17+
* @param mixed $stats
18+
*/
19+
public function testLINEST($expectedResult, $yValues, $xValues, $const, $stats): void
20+
{
21+
$result = Statistical::LINEST($yValues, $xValues, $const, $stats);
22+
23+
$elements = count($expectedResult);
24+
for ($element = 0; $element < $elements; ++$element) {
25+
self::assertEqualsWithDelta($expectedResult[$element], $result[$element], 1E-12);
26+
}
27+
}
28+
29+
public function providerLINEST()
30+
{
31+
return require 'tests/data/Calculation/Statistical/LINEST.php';
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
4+
5+
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class LogEstTest extends TestCase
9+
{
10+
/**
11+
* @dataProvider providerLOGEST
12+
*
13+
* @param mixed $expectedResult
14+
* @param mixed $xValues
15+
* @param mixed $yValues
16+
* @param mixed $const
17+
* @param mixed $stats
18+
*/
19+
public function testLOGEST($expectedResult, $yValues, $xValues, $const, $stats): void
20+
{
21+
$result = Statistical::LOGEST($yValues, $xValues, $const, $stats);
22+
23+
$elements = count($expectedResult);
24+
for ($element = 0; $element < $elements; ++$element) {
25+
self::assertEqualsWithDelta($expectedResult[$element], $result[$element], 1E-12);
26+
}
27+
}
28+
29+
public function providerLOGEST()
30+
{
31+
return require 'tests/data/Calculation/Statistical/LOGEST.php';
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
4+
5+
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class LogInvTest extends TestCase
9+
{
10+
/**
11+
* @dataProvider providerLOGINV
12+
*
13+
* @param mixed $expectedResult
14+
*/
15+
public function testLOGINV($expectedResult, ...$args): void
16+
{
17+
$result = Statistical::LOGINV(...$args);
18+
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
19+
}
20+
21+
public function providerLOGINV(): array
22+
{
23+
return require 'tests/data/Calculation/Statistical/LOGINV.php';
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
4+
5+
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class MaxATest extends TestCase
9+
{
10+
/**
11+
* @dataProvider providerMAXA
12+
*
13+
* @param mixed $expectedResult
14+
*/
15+
public function testMAXA($expectedResult, ...$args): void
16+
{
17+
$result = Statistical::MAXA(...$args);
18+
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
19+
}
20+
21+
public function providerMAXA(): array
22+
{
23+
return require 'tests/data/Calculation/Statistical/MAXA.php';
24+
}
25+
}

0 commit comments

Comments
 (0)