Files
PhpSpreadsheet/tests/data/Calculation/Statistical/BETAINV.php
T
Vincent Gao f687d261e8 Fix BETAINV false convergence when the Beta CDF underflows
calculateInverse() treated a CDF value of exactly 0.0 as "the guess is the
root" and collapsed the bracket with $b = $a, ending the search. inverse()
already rejects probability <= 0, so a CDF of 0.0 inside the bisection can
only be a float64 underflow at a guess far below the root - never an exact
hit. It is just an ordinary "guess too low" and belongs in the existing
else branch.

The underflow is reached whenever a probe lands many standard deviations
from the mean, so the search collapses after two or three iterations and
returns whichever midpoint it was holding. BETAINV(0.5, 5000, 5000) gave
0.25, though Beta(a, a) is symmetric and its median is exactly 0.5;
BETAINV(0.5, 20000, 3) gave 0.5 against a true 0.99986. Onset is around
alpha = 1080 for beta = 1, where the closed form 0.5 ** (1 / alpha) is
available to check against.

That test also happened to stop the search for shapes where incompleteBeta
declines to evaluate at all and returns 0 for every x, so inverse() now
rejects alpha + beta above that documented limit up front: the CDF is
identically zero there, so no quantile exists to search for.

Tests cover a shape x probability grid against scipy reference values plus
three checks that need no external oracle: the symmetric median, the
Beta(alpha, 1) closed form, and the BETADIST round trip / mirror identity.
2026-08-05 12:28:05 +02:00

141 lines
2.8 KiB
PHP

<?php
declare(strict_types=1);
return [
[
1.862243320728,
0.52, 3, 4, 1, 3,
],
[
2.164759759129,
0.3, 7.5, 9, 1, 4,
],
[
2.164759759129,
0.3, 7.5, 9, 4, 1,
],
[
7.761240188783,
0.75, 8, 9, 5, 10,
],
[
2.0,
0.685470581055, 8, 10, 1, 3,
],
[
0.303225844664,
0.2, 4, 5, 0, 1,
],
[
0.303225844664,
0.2, 4, 5, null, null,
],
[
'#VALUE!',
'NAN', 4, 5, 0, 1,
],
[
'#VALUE!',
0.2, 'NAN', 5, 0, 1,
],
[
'#VALUE!',
0.2, 4, 'NAN', 0, 1,
],
[
'#VALUE!',
0.2, 4, 5, 'NAN', 1,
],
[
'#VALUE!',
0.2, 4, 5, 0, 'NAN',
],
// Large shape parameters: the CDF underflows to 0 at the low probes of the
// bisection long before the root is reached. Onset is alpha ~ 1080 for beta = 1.
'symmetric, median' => [
0.5,
0.5, 5000, 5000, 0, 1,
],
'symmetric, upper quartile' => [
0.503372494704,
0.75, 5000, 5000, 0, 1,
],
'symmetric, lower decile' => [
0.493592345088,
0.1, 5000, 5000, 0, 1,
],
'symmetric, median, alpha = beta = 20000' => [
0.5,
0.5, 20000, 20000, 0, 1,
],
'symmetric, scaled to [1, 3]' => [
2.006744989408,
0.75, 5000, 5000, 1, 3,
],
'beta = 1, closed form 0.5 ** (1 / alpha)' => [
0.999861380173,
0.5, 5000, 1, 0, 1,
],
'beta = 1, just above the onset' => [
0.999370064692,
0.5, 1100, 1, 0, 1,
],
'right-skewed, alpha >> beta' => [
0.999866312606,
0.5, 20000, 3, 0, 1,
],
'left-skewed, beta >> alpha' => [
0.000133687394,
0.5, 3, 20000, 0, 1,
],
'moderately large alpha' => [
0.973403556565,
0.25, 2000, 50, 0, 1,
],
'alpha so large that the quantile rounds to 1' => [
1.0,
0.5, 1.0e20, 3, 0, 1,
],
'huge symmetric shapes still give the median' => [
0.5,
0.5, 1.0e20, 1.0e20, 0, 1,
],
'alpha + beta beyond the range incompleteBeta will evaluate' => [
'#NUM!',
0.5, 2.0e305, 1.0e305, 0, 1,
],
'alpha < 0' => [
'#NUM!',
0.2, -4, 5, 0, 1,
],
'alpha = 0' => [
'#NUM!',
0.2, 0, 5, 0, 1,
],
'beta < 0' => [
'#NUM!',
0.2, 4, -5, 0, 1,
],
'beta = 0' => [
'#NUM!',
0.2, 4, 0, 0, 1,
],
'Probability < 0' => [
'#NUM!',
-0.5, 4, 5, 1, 3,
],
'Probability = 0' => [
'#NUM!',
0.0, 4, 5, 1, 3,
],
'Probability > 1' => [
'#NUM!',
1.5, 4, 5, 1, 3,
],
'Min = Max' => [
'#NUM!',
1, 4, 5, 1, 1,
],
];