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