@@ 1090-1136 (lines=47) @@ | ||
1087 | * |
|
1088 | * @return float |
|
1089 | */ |
|
1090 | public static function CHIINV($probability, $degrees) |
|
1091 | { |
|
1092 | $probability = Functions::flattenSingleValue($probability); |
|
1093 | $degrees = floor(Functions::flattenSingleValue($degrees)); |
|
1094 | ||
1095 | if ((is_numeric($probability)) && (is_numeric($degrees))) { |
|
1096 | $xLo = 100; |
|
1097 | $xHi = 0; |
|
1098 | ||
1099 | $x = $xNew = 1; |
|
1100 | $dx = 1; |
|
1101 | $i = 0; |
|
1102 | ||
1103 | while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { |
|
1104 | // Apply Newton-Raphson step |
|
1105 | $result = self::CHIDIST($x, $degrees); |
|
1106 | $error = $result - $probability; |
|
1107 | if ($error == 0.0) { |
|
1108 | $dx = 0; |
|
1109 | } elseif ($error < 0.0) { |
|
1110 | $xLo = $x; |
|
1111 | } else { |
|
1112 | $xHi = $x; |
|
1113 | } |
|
1114 | // Avoid division by zero |
|
1115 | if ($result != 0.0) { |
|
1116 | $dx = $error / $result; |
|
1117 | $xNew = $x - $dx; |
|
1118 | } |
|
1119 | // If the NR fails to converge (which for example may be the |
|
1120 | // case if the initial guess is too rough) we apply a bisection |
|
1121 | // step to determine a more narrow interval around the root. |
|
1122 | if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { |
|
1123 | $xNew = ($xLo + $xHi) / 2; |
|
1124 | $dx = $xNew - $x; |
|
1125 | } |
|
1126 | $x = $xNew; |
|
1127 | } |
|
1128 | if ($i == MAX_ITERATIONS) { |
|
1129 | return Functions::NA(); |
|
1130 | } |
|
1131 | ||
1132 | return round($x, 12); |
|
1133 | } |
|
1134 | ||
1135 | return Functions::VALUE(); |
|
1136 | } |
|
1137 | ||
1138 | /** |
|
1139 | * CONFIDENCE. |
|
@@ 3466-3512 (lines=47) @@ | ||
3463 | * |
|
3464 | * @return float |
|
3465 | */ |
|
3466 | public static function TINV($probability, $degrees) |
|
3467 | { |
|
3468 | $probability = Functions::flattenSingleValue($probability); |
|
3469 | $degrees = floor(Functions::flattenSingleValue($degrees)); |
|
3470 | ||
3471 | if ((is_numeric($probability)) && (is_numeric($degrees))) { |
|
3472 | $xLo = 100; |
|
3473 | $xHi = 0; |
|
3474 | ||
3475 | $x = $xNew = 1; |
|
3476 | $dx = 1; |
|
3477 | $i = 0; |
|
3478 | ||
3479 | while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { |
|
3480 | // Apply Newton-Raphson step |
|
3481 | $result = self::TDIST($x, $degrees, 2); |
|
3482 | $error = $result - $probability; |
|
3483 | if ($error == 0.0) { |
|
3484 | $dx = 0; |
|
3485 | } elseif ($error < 0.0) { |
|
3486 | $xLo = $x; |
|
3487 | } else { |
|
3488 | $xHi = $x; |
|
3489 | } |
|
3490 | // Avoid division by zero |
|
3491 | if ($result != 0.0) { |
|
3492 | $dx = $error / $result; |
|
3493 | $xNew = $x - $dx; |
|
3494 | } |
|
3495 | // If the NR fails to converge (which for example may be the |
|
3496 | // case if the initial guess is too rough) we apply a bisection |
|
3497 | // step to determine a more narrow interval around the root. |
|
3498 | if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { |
|
3499 | $xNew = ($xLo + $xHi) / 2; |
|
3500 | $dx = $xNew - $x; |
|
3501 | } |
|
3502 | $x = $xNew; |
|
3503 | } |
|
3504 | if ($i == MAX_ITERATIONS) { |
|
3505 | return Functions::NA(); |
|
3506 | } |
|
3507 | ||
3508 | return round($x, 12); |
|
3509 | } |
|
3510 | ||
3511 | return Functions::VALUE(); |
|
3512 | } |
|
3513 | ||
3514 | /** |
|
3515 | * TREND. |