@@ 1043-1087 (lines=45) @@ | ||
1040 | * @param float $degrees degrees of freedom |
|
1041 | * @return float |
|
1042 | */ |
|
1043 | public static function CHIINV($probability, $degrees) { |
|
1044 | $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); |
|
1045 | $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees)); |
|
1046 | ||
1047 | if ((is_numeric($probability)) && (is_numeric($degrees))) { |
|
1048 | ||
1049 | $xLo = 100; |
|
1050 | $xHi = 0; |
|
1051 | ||
1052 | $x = $xNew = 1; |
|
1053 | $dx = 1; |
|
1054 | $i = 0; |
|
1055 | ||
1056 | while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { |
|
1057 | // Apply Newton-Raphson step |
|
1058 | $result = self::CHIDIST($x, $degrees); |
|
1059 | $error = $result - $probability; |
|
1060 | if ($error == 0.0) { |
|
1061 | $dx = 0; |
|
1062 | } elseif ($error < 0.0) { |
|
1063 | $xLo = $x; |
|
1064 | } else { |
|
1065 | $xHi = $x; |
|
1066 | } |
|
1067 | // Avoid division by zero |
|
1068 | if ($result != 0.0) { |
|
1069 | $dx = $error / $result; |
|
1070 | $xNew = $x - $dx; |
|
1071 | } |
|
1072 | // If the NR fails to converge (which for example may be the |
|
1073 | // case if the initial guess is too rough) we apply a bisection |
|
1074 | // step to determine a more narrow interval around the root. |
|
1075 | if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { |
|
1076 | $xNew = ($xLo + $xHi) / 2; |
|
1077 | $dx = $xNew - $x; |
|
1078 | } |
|
1079 | $x = $xNew; |
|
1080 | } |
|
1081 | if ($i == MAX_ITERATIONS) { |
|
1082 | return PHPExcel_Calculation_Functions::NA(); |
|
1083 | } |
|
1084 | return round($x,12); |
|
1085 | } |
|
1086 | return PHPExcel_Calculation_Functions::VALUE(); |
|
1087 | } // function CHIINV() |
|
1088 | ||
1089 | ||
1090 | /** |
|
@@ 3272-3315 (lines=44) @@ | ||
3269 | * @param float $degrees degrees of freedom |
|
3270 | * @return float |
|
3271 | */ |
|
3272 | public static function TINV($probability, $degrees) { |
|
3273 | $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); |
|
3274 | $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees)); |
|
3275 | ||
3276 | if ((is_numeric($probability)) && (is_numeric($degrees))) { |
|
3277 | $xLo = 100; |
|
3278 | $xHi = 0; |
|
3279 | ||
3280 | $x = $xNew = 1; |
|
3281 | $dx = 1; |
|
3282 | $i = 0; |
|
3283 | ||
3284 | while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { |
|
3285 | // Apply Newton-Raphson step |
|
3286 | $result = self::TDIST($x, $degrees, 2); |
|
3287 | $error = $result - $probability; |
|
3288 | if ($error == 0.0) { |
|
3289 | $dx = 0; |
|
3290 | } elseif ($error < 0.0) { |
|
3291 | $xLo = $x; |
|
3292 | } else { |
|
3293 | $xHi = $x; |
|
3294 | } |
|
3295 | // Avoid division by zero |
|
3296 | if ($result != 0.0) { |
|
3297 | $dx = $error / $result; |
|
3298 | $xNew = $x - $dx; |
|
3299 | } |
|
3300 | // If the NR fails to converge (which for example may be the |
|
3301 | // case if the initial guess is too rough) we apply a bisection |
|
3302 | // step to determine a more narrow interval around the root. |
|
3303 | if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { |
|
3304 | $xNew = ($xLo + $xHi) / 2; |
|
3305 | $dx = $xNew - $x; |
|
3306 | } |
|
3307 | $x = $xNew; |
|
3308 | } |
|
3309 | if ($i == MAX_ITERATIONS) { |
|
3310 | return PHPExcel_Calculation_Functions::NA(); |
|
3311 | } |
|
3312 | return round($x,12); |
|
3313 | } |
|
3314 | return PHPExcel_Calculation_Functions::VALUE(); |
|
3315 | } // function TINV() |
|
3316 | ||
3317 | ||
3318 | /** |