Extract Poisson distribution into its own class (#1953)

This commit is contained in:
Mark Baker 2021-03-26 09:08:23 +01:00 committed by GitHub
parent f51c19c125
commit c380b25d3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 138 additions and 88 deletions

View File

@ -1963,12 +1963,12 @@ class Calculation
],
'POISSON' => [
'category' => Category::CATEGORY_STATISTICAL,
'functionCall' => [Statistical::class, 'POISSON'],
'functionCall' => [Statistical\Distributions\Poisson::class, 'distribution'],
'argumentCount' => '3',
],
'POISSON.DIST' => [
'category' => Category::CATEGORY_STATISTICAL,
'functionCall' => [Statistical::class, 'POISSON'],
'functionCall' => [Statistical\Distributions\Poisson::class, 'distribution'],
'argumentCount' => '3',
],
'POWER' => [

View File

@ -22,7 +22,7 @@ class Days360
* PHP DateTime object, or a standard date string
* @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer),
* PHP DateTime object, or a standard date string
* @param bool $method US or European Method
* @param mixed (bool) $method US or European Method
* FALSE or omitted: U.S. (NASD) method. If the starting date is
* the last day of a month, it becomes equal to the 30th of the
* same month. If the ending date is the last day of a month and

View File

@ -16,9 +16,9 @@ class Complex
* Excel Function:
* COMPLEX(realNumber,imaginary[,suffix])
*
* @param float $realNumber the real coefficient of the complex number
* @param float $imaginary the imaginary coefficient of the complex number
* @param string $suffix The suffix for the imaginary component of the complex number.
* @param mixed (float) $realNumber the real coefficient of the complex number
* @param mixed (float) $imaginary the imaginary coefficient of the complex number
* @param mixed (string) $suffix The suffix for the imaginary component of the complex number.
* If omitted, the suffix is assumed to be "i".
*
* @return string

View File

@ -42,15 +42,15 @@ class Financial
* @param mixed $settlement The security's settlement date.
* The security settlement date is the date after the issue date
* when the security is traded to the buyer.
* @param float $rate the security's annual coupon rate
* @param float $par The security's par value.
* @param mixed (float) $rate the security's annual coupon rate
* @param mixed (float) $par The security's par value.
* If you omit par, ACCRINT uses $1,000.
* @param int $frequency the number of coupon payments per year.
* @param mixed (int) $frequency the number of coupon payments per year.
* Valid frequency values are:
* 1 Annual
* 2 Semi-Annual
* 4 Quarterly
* @param int $basis The type of day count to use.
* @param mixed (int) $basis The type of day count to use.
* 0 or omitted US (NASD) 30/360
* 1 Actual/actual
* 2 Actual/360
@ -98,10 +98,10 @@ class Financial
*
* @param mixed $issue The security's issue date
* @param mixed $settlement The security's settlement (or maturity) date
* @param float $rate The security's annual coupon rate
* @param float $par The security's par value.
* @param mixed (float) $rate The security's annual coupon rate
* @param mixed (float) $par The security's par value.
* If you omit par, ACCRINT uses $1,000.
* @param int $basis The type of day count to use.
* @param mixed (int) $basis The type of day count to use.
* 0 or omitted US (NASD) 30/360
* 1 Actual/actual
* 2 Actual/360
@ -890,11 +890,11 @@ class Financial
* Excel Function:
* IRR(values[,guess])
*
* @param float[] $values An array or a reference to cells that contain numbers for which you want
* @param mixed (float[]) $values An array or a reference to cells that contain numbers for which you want
* to calculate the internal rate of return.
* Values must contain at least one positive value and one negative value to
* calculate the internal rate of return.
* @param float $guess A number that you guess is close to the result of IRR
* @param mixed (float) $guess A number that you guess is close to the result of IRR
*
* @return float|string
*/
@ -1000,11 +1000,11 @@ class Financial
* Excel Function:
* MIRR(values,finance_rate, reinvestment_rate)
*
* @param float[] $values An array or a reference to cells that contain a series of payments and
* @param mixed (float[]) $values An array or a reference to cells that contain a series of payments and
* income occurring at regular intervals.
* Payments are negative value, income is positive values.
* @param float $finance_rate The interest rate you pay on the money used in the cash flows
* @param float $reinvestment_rate The interest rate you receive on the cash flows as you reinvest them
* @param mixed (float) $finance_rate The interest rate you pay on the money used in the cash flows
* @param mixed (float) $reinvestment_rate The interest rate you receive on the cash flows as you reinvest them
*
* @return float|string Result, or a string containing an error
*/
@ -1371,20 +1371,20 @@ class Financial
* Excel Function:
* RATE(nper,pmt,pv[,fv[,type[,guess]]])
*
* @param float $nper The total number of payment periods in an annuity
* @param float $pmt The payment made each period and cannot change over the life
* @param mixed (float) $nper The total number of payment periods in an annuity
* @param mixed (float) $pmt The payment made each period and cannot change over the life
* of the annuity.
* Typically, pmt includes principal and interest but no other
* fees or taxes.
* @param float $pv The present value - the total amount that a series of future
* @param mixed (float) $pv The present value - the total amount that a series of future
* payments is worth now
* @param float $fv The future value, or a cash balance you want to attain after
* @param mixed (float) $fv The future value, or a cash balance you want to attain after
* the last payment is made. If fv is omitted, it is assumed
* to be 0 (the future value of a loan, for example, is 0).
* @param int $type A number 0 or 1 and indicates when payments are due:
* @param mixed (int) $type A number 0 or 1 and indicates when payments are due:
* 0 or omitted At the end of the period.
* 1 At the beginning of the period.
* @param float $guess Your guess for what the rate will be.
* @param mixed (float) $guess Your guess for what the rate will be.
* If you omit guess, it is assumed to be 10 percent.
*
* @return float|string
@ -1443,9 +1443,9 @@ class Financial
* The security settlement date is the date after the issue date when the security is traded to the buyer.
* @param mixed $maturity The security's maturity date.
* The maturity date is the date when the security expires.
* @param int $investment The amount invested in the security
* @param int $discount The security's discount rate
* @param int $basis The type of day count to use.
* @param mixed (int) $investment The amount invested in the security
* @param mixed (int) $discount The security's discount rate
* @param mixed (int) $basis The type of day count to use.
* 0 or omitted US (NASD) 30/360
* 1 Actual/actual
* 2 Actual/360

View File

@ -137,9 +137,9 @@ class Depreciation
*
* Returns the straight-line depreciation of an asset for one period
*
* @param mixed $cost Initial cost of the asset
* @param mixed $salvage Value at the end of the depreciation
* @param mixed $life Number of periods over which the asset is depreciated
* @param mixed (float) $cost Initial cost of the asset
* @param mixed (float) $salvage Value at the end of the depreciation
* @param mixed (float) $life Number of periods over which the asset is depreciated
*
* @return float|string Result, or a string containing an error
*/
@ -169,10 +169,10 @@ class Depreciation
*
* Returns the sum-of-years' digits depreciation of an asset for a specified period.
*
* @param mixed $cost Initial cost of the asset
* @param mixed $salvage Value at the end of the depreciation
* @param mixed $life Number of periods over which the asset is depreciated
* @param mixed $period Period
* @param mixed (float) $cost Initial cost of the asset
* @param mixed (float) $salvage Value at the end of the depreciation
* @param mixed (float) $life Number of periods over which the asset is depreciated
* @param mixed (float) $period Period
*
* @return float|string Result, or a string containing an error
*/

View File

@ -576,7 +576,7 @@ class Functions
/**
* Convert a multi-dimensional array to a simple 1-dimensional array.
*
* @param array $array Array to be flattened
* @param mixed (array) $array Array to be flattened
*
* @return array Flattened array
*/
@ -609,7 +609,7 @@ class Functions
/**
* Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing.
*
* @param array $array Array to be flattened
* @param mixed (array) $array Array to be flattened
*
* @return array Flattened array
*/

View File

@ -148,8 +148,8 @@ class LookupRef
* Excel Function:
* =HYPERLINK(linkURL,displayName)
*
* @param string $linkURL Value to check, is also the value returned when no error
* @param string $displayName Value to return when testValue is an error condition
* @param mixed (string) $linkURL Value to check, is also the value returned when no error
* @param mixed (string) $displayName Value to return when testValue is an error condition
* @param Cell $pCell The cell to set the hyperlink in
*
* @return mixed The value of $displayName (or $linkURL if $displayName was blank)

View File

@ -9,7 +9,7 @@ class Matrix
/**
* TRANSPOSE.
*
* @param array $matrixData A matrix of values
* @param mixed (array) $matrixData A matrix of values
*
* @return array
*/

View File

@ -251,10 +251,10 @@ class Statistical
* experiment. For example, BINOMDIST can calculate the probability that two of the next three
* babies born are male.
*
* @param float $value Number of successes in trials
* @param float $trials Number of trials
* @param float $probability Probability of success on each trial
* @param bool $cumulative
* @param mixed (float) $value Number of successes in trials
* @param mixed (float) $trials Number of trials
* @param mixed (float) $probability Probability of success on each trial
* @param mixed (bool) $cumulative
*
* @return float|string
*/
@ -1502,9 +1502,9 @@ class Statistical
* distribution, except that the number of successes is fixed, and the number of trials is
* variable. Like the binomial, trials are assumed to be independent.
*
* @param float $failures Number of Failures
* @param float $successes Threshold number of Successes
* @param float $probability Probability of success on each trial
* @param mixed (float) $failures Number of Failures
* @param mixed (float) $successes Threshold number of Successes
* @param mixed (float) $probability Probability of success on each trial
*
* @return float|string The result, or a string containing an error
*/
@ -1539,10 +1539,10 @@ class Statistical
* function has a very wide range of applications in statistics, including hypothesis
* testing.
*
* @param float $value
* @param float $mean Mean Value
* @param float $stdDev Standard Deviation
* @param bool $cumulative
* @param mixed (float) $value
* @param mixed (float) $mean Mean Value
* @param mixed (float) $stdDev Standard Deviation
* @param mixed (bool) $cumulative
*
* @return float|string The result, or a string containing an error
*/
@ -1573,9 +1573,9 @@ class Statistical
*
* Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
*
* @param float $probability
* @param float $mean Mean Value
* @param float $stdDev Standard Deviation
* @param mixed (float) $probability
* @param mixed (float) $mean Mean Value
* @param mixed (float) $stdDev Standard Deviation
*
* @return float|string The result, or a string containing an error
*/
@ -1606,7 +1606,7 @@ class Statistical
* a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
* table of standard normal curve areas.
*
* @param float $value
* @param mixed (float) $value
*
* @return float|string The result, or a string containing an error
*/
@ -1627,8 +1627,8 @@ class Statistical
* a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
* table of standard normal curve areas.
*
* @param float $value
* @param bool $cumulative
* @param mixed (float) $value
* @param mixed (bool) $cumulative
*
* @return float|string The result, or a string containing an error
*/
@ -1648,7 +1648,7 @@ class Statistical
*
* Returns the inverse of the standard normal cumulative distribution
*
* @param float $value
* @param mixed (float) $value
*
* @return float|string The result, or a string containing an error
*/
@ -1714,9 +1714,9 @@ class Statistical
* rather than floored (as MS Excel), so value 3 for a value set of 1, 2, 3, 4 will return
* 0.667 rather than 0.666
*
* @param float[] $valueSet An array of, or a reference to, a list of numbers
* @param int $value the number whose rank you want to find
* @param int $significance the number of significant digits for the returned percentage value
* @param mixed (float[]) $valueSet An array of, or a reference to, a list of numbers
* @param mixed (int) $value the number whose rank you want to find
* @param mixed (int) $significance the number of significant digits for the returned percentage value
*
* @return float|string (string if result is an error)
*/
@ -1787,37 +1787,20 @@ class Statistical
* is predicting the number of events over a specific time, such as the number of
* cars arriving at a toll plaza in 1 minute.
*
* @param float $value
* @param float $mean Mean Value
* @param bool $cumulative
* @Deprecated 1.18.0
*
* @see Statistical\Distributions\Poisson::distribution()
* Use the distribution() method in the Statistical\Distributions\Poisson class instead
*
* @param mixed (float) $value
* @param mixed (float) $mean Mean Value
* @param mixed (bool) $cumulative
*
* @return float|string The result, or a string containing an error
*/
public static function POISSON($value, $mean, $cumulative)
{
$value = Functions::flattenSingleValue($value);
$mean = Functions::flattenSingleValue($mean);
if ((is_numeric($value)) && (is_numeric($mean))) {
if (($value < 0) || ($mean <= 0)) {
return Functions::NAN();
}
if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
if ($cumulative) {
$summer = 0;
$floor = floor($value);
for ($i = 0; $i <= $floor; ++$i) {
$summer += $mean ** $i / MathTrig::FACT($i);
}
return exp(0 - $mean) * $summer;
}
return (exp(0 - $mean) * $mean ** $value) / MathTrig::FACT($value);
}
}
return Functions::VALUE();
return Statistical\Distributions\Poisson::distribution($value, $mean, $cumulative);
}
/**

View File

@ -0,0 +1,55 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
class Poisson
{
use BaseValidations;
/**
* POISSON.
*
* Returns the Poisson distribution. A common application of the Poisson distribution
* is predicting the number of events over a specific time, such as the number of
* cars arriving at a toll plaza in 1 minute.
*
* @param mixed (float) $value
* @param mixed (float) $mean Mean Value
* @param mixed (bool) $cumulative
*
* @return float|string The result, or a string containing an error
*/
public static function distribution($value, $mean, $cumulative)
{
$value = Functions::flattenSingleValue($value);
$mean = Functions::flattenSingleValue($mean);
try {
$value = self::validateFloat($value);
$mean = self::validateFloat($mean);
$cumulative = self::validateBool($cumulative);
} catch (Exception $e) {
return $e->getMessage();
}
if (($value < 0) || ($mean < 0)) {
return Functions::NAN();
}
if ($cumulative) {
$summer = 0;
$floor = floor($value);
for ($i = 0; $i <= $floor; ++$i) {
$summer += $mean ** $i / MathTrig::FACT($i);
}
return exp(0 - $mean) * $summer;
}
return (exp(0 - $mean) * $mean ** $value) / MathTrig::FACT($value);
}
}

View File

@ -18,11 +18,23 @@ return [
35, 40, true,
],
[
'#NUM!',
35, -40, true,
'#VALUE!',
'Nan', 40, true,
],
[
'#VALUE!',
35, 'Nan', true,
],
[
'#VALUE!',
35, 40, 'Nan',
],
'Value < 0' => [
'#NUM!',
-35, 40, true,
],
'Mean < 0' => [
'#NUM!',
35, -40, true,
],
];