Extract Permutation functions from the Statistical class into a dedicated Permutations class (#1851)

* Extract Permutation functions from the Statistical class into a dedicated Permutations class

Retain the original methods in the Statistical class as stubs for BC, but deprecate them. They will be removed for PHPSpreadsheet v2

Note that unit tests still point to the Statistical class stubs; these should be modified to use the Permutations class directly when the stubs are removed

Also provided a basic implementationof the PERMUTATIONA() Function
This commit is contained in:
Mark Baker 2021-02-13 15:35:07 +01:00 committed by GitHub
parent e824caf857
commit 42ecc270ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 138 additions and 15 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
- Implemented DataBar for conditional formatting in Xlsx, providing read/write and creation of (type, value, direction, fills, border, axis position, color settings) as DataBar options in Excel. [#1754](https://github.com/PHPOffice/PhpSpreadsheet/pull/1754)
- Alignment for ODS Writer [#1796](https://github.com/PHPOffice/PhpSpreadsheet/issues/1796)
- Basic implementation of the PERMUTATIONA() Statistical Function
### Changed

View File

@ -1932,12 +1932,12 @@ class Calculation
],
'PERMUT' => [
'category' => Category::CATEGORY_STATISTICAL,
'functionCall' => [Statistical::class, 'PERMUT'],
'functionCall' => [Statistical\Permutations::class, 'PERMUT'],
'argumentCount' => '2',
],
'PERMUTATIONA' => [
'category' => Category::CATEGORY_STATISTICAL,
'functionCall' => [Functions::class, 'DUMMY'],
'functionCall' => [Statistical\Permutations::class, 'PERMUTATIONA'],
'argumentCount' => '2',
],
'PHONETIC' => [

View File

@ -2923,6 +2923,8 @@ class Statistical
* combinations, for which the internal order is not significant. Use this function
* for lottery-style probability calculations.
*
* @Deprecated 2.0.0 Use the PERMUT() method in the Statistical\Permutations class instead
*
* @param int $numObjs Number of different objects
* @param int $numInSet Number of objects in each permutation
*
@ -2930,19 +2932,7 @@ class Statistical
*/
public static function PERMUT($numObjs, $numInSet)
{
$numObjs = Functions::flattenSingleValue($numObjs);
$numInSet = Functions::flattenSingleValue($numInSet);
if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
$numInSet = floor($numInSet);
if ($numObjs < $numInSet) {
return Functions::NAN();
}
return round(MathTrig::FACT($numObjs) / MathTrig::FACT($numObjs - $numInSet));
}
return Functions::VALUE();
return Statistical\Permutations::PERMUT($numObjs, $numInSet);
}
/**

View File

@ -0,0 +1,69 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
class Permutations
{
/**
* PERMUT.
*
* Returns the number of permutations for a given number of objects that can be
* selected from number objects. A permutation is any set or subset of objects or
* events where internal order is significant. Permutations are different from
* combinations, for which the internal order is not significant. Use this function
* for lottery-style probability calculations.
*
* @param int $numObjs Number of different objects
* @param int $numInSet Number of objects in each permutation
*
* @return int|string Number of permutations, or a string containing an error
*/
public static function PERMUT($numObjs, $numInSet)
{
$numObjs = Functions::flattenSingleValue($numObjs);
$numInSet = Functions::flattenSingleValue($numInSet);
if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
$numInSet = floor($numInSet);
if ($numObjs < $numInSet) {
return Functions::NAN();
}
return round(MathTrig::FACT($numObjs) / MathTrig::FACT($numObjs - $numInSet));
}
return Functions::VALUE();
}
/**
* PERMUTATIONA.
*
* Returns the number of permutations for a given number of objects (with repetitions)
* that can be selected from the total objects.
*
* @param int $numObjs Number of different objects
* @param int $numInSet Number of objects in each permutation
*
* @return int|string Number of permutations, or a string containing an error
*/
public static function PERMUTATIONA($numObjs, $numInSet)
{
$numObjs = Functions::flattenSingleValue($numObjs);
$numInSet = Functions::flattenSingleValue($numInSet);
if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
$numObjs = floor($numObjs);
$numInSet = floor($numInSet);
if ($numObjs < 0 || $numInSet < 0) {
return Functions::NAN();
}
return $numObjs ** $numInSet;
}
return Functions::VALUE();
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Permutations;
use PHPUnit\Framework\TestCase;
class PermutationATest extends TestCase
{
protected function setUp(): void
{
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
}
/**
* @dataProvider providerPERMUT
*
* @param mixed $expectedResult
*/
public function testPERMUT($expectedResult, ...$args): void
{
$result = Permutations::PERMUTATIONA(...$args);
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
}
public function providerPERMUT()
{
return require 'tests/data/Calculation/Statistical/PERMUTATIONA.php';
}
}

View File

@ -45,6 +45,10 @@ return [
10068347520,
49, 6,
],
[
'#NUM!',
2, 3,
],
[
'#NUM!',
1, 2,

View File

@ -0,0 +1,28 @@
<?php
return [
[
5,
5, 1,
],
[
2,
2.2, 1.1,
],
[
5,
5.1, 1.9,
],
[
1,
1, 2,
],
[
'#NUM!',
-1, 2,
],
[
'#VALUE!',
49, 'NaN',
],
];