@@ 1055-1101 (lines=47) @@ | ||
1052 | * @param float $degrees degrees of freedom |
|
1053 | * @return float |
|
1054 | */ |
|
1055 | public static function CHIINV($probability, $degrees) |
|
1056 | { |
|
1057 | $probability = Functions::flattenSingleValue($probability); |
|
1058 | $degrees = floor(Functions::flattenSingleValue($degrees)); |
|
1059 | ||
1060 | if ((is_numeric($probability)) && (is_numeric($degrees))) { |
|
1061 | $xLo = 100; |
|
1062 | $xHi = 0; |
|
1063 | ||
1064 | $x = $xNew = 1; |
|
1065 | $dx = 1; |
|
1066 | $i = 0; |
|
1067 | ||
1068 | while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { |
|
1069 | // Apply Newton-Raphson step |
|
1070 | $result = self::CHIDIST($x, $degrees); |
|
1071 | $error = $result - $probability; |
|
1072 | if ($error == 0.0) { |
|
1073 | $dx = 0; |
|
1074 | } elseif ($error < 0.0) { |
|
1075 | $xLo = $x; |
|
1076 | } else { |
|
1077 | $xHi = $x; |
|
1078 | } |
|
1079 | // Avoid division by zero |
|
1080 | if ($result != 0.0) { |
|
1081 | $dx = $error / $result; |
|
1082 | $xNew = $x - $dx; |
|
1083 | } |
|
1084 | // If the NR fails to converge (which for example may be the |
|
1085 | // case if the initial guess is too rough) we apply a bisection |
|
1086 | // step to determine a more narrow interval around the root. |
|
1087 | if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { |
|
1088 | $xNew = ($xLo + $xHi) / 2; |
|
1089 | $dx = $xNew - $x; |
|
1090 | } |
|
1091 | $x = $xNew; |
|
1092 | } |
|
1093 | if ($i == MAX_ITERATIONS) { |
|
1094 | return Functions::NA(); |
|
1095 | } |
|
1096 | ||
1097 | return round($x, 12); |
|
1098 | } |
|
1099 | ||
1100 | return Functions::VALUE(); |
|
1101 | } |
|
1102 | ||
1103 | /** |
|
1104 | * CONFIDENCE |
|
@@ 3313-3359 (lines=47) @@ | ||
3310 | * @param float $degrees degrees of freedom |
|
3311 | * @return float |
|
3312 | */ |
|
3313 | public static function TINV($probability, $degrees) |
|
3314 | { |
|
3315 | $probability = Functions::flattenSingleValue($probability); |
|
3316 | $degrees = floor(Functions::flattenSingleValue($degrees)); |
|
3317 | ||
3318 | if ((is_numeric($probability)) && (is_numeric($degrees))) { |
|
3319 | $xLo = 100; |
|
3320 | $xHi = 0; |
|
3321 | ||
3322 | $x = $xNew = 1; |
|
3323 | $dx = 1; |
|
3324 | $i = 0; |
|
3325 | ||
3326 | while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { |
|
3327 | // Apply Newton-Raphson step |
|
3328 | $result = self::TDIST($x, $degrees, 2); |
|
3329 | $error = $result - $probability; |
|
3330 | if ($error == 0.0) { |
|
3331 | $dx = 0; |
|
3332 | } elseif ($error < 0.0) { |
|
3333 | $xLo = $x; |
|
3334 | } else { |
|
3335 | $xHi = $x; |
|
3336 | } |
|
3337 | // Avoid division by zero |
|
3338 | if ($result != 0.0) { |
|
3339 | $dx = $error / $result; |
|
3340 | $xNew = $x - $dx; |
|
3341 | } |
|
3342 | // If the NR fails to converge (which for example may be the |
|
3343 | // case if the initial guess is too rough) we apply a bisection |
|
3344 | // step to determine a more narrow interval around the root. |
|
3345 | if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { |
|
3346 | $xNew = ($xLo + $xHi) / 2; |
|
3347 | $dx = $xNew - $x; |
|
3348 | } |
|
3349 | $x = $xNew; |
|
3350 | } |
|
3351 | if ($i == MAX_ITERATIONS) { |
|
3352 | return Functions::NA(); |
|
3353 | } |
|
3354 | ||
3355 | return round($x, 12); |
|
3356 | } |
|
3357 | ||
3358 | return Functions::VALUE(); |
|
3359 | } |
|
3360 | ||
3361 | /** |
|
3362 | * TREND |