picomath

Perl

normal_cdf_inverse.pl

sub rational_approximation {
    my $t = $_[0];

    # Abramowitz and Stegun formula 26.2.23.
    # The absolute value of the error should be less than 4.5 e-4.
    my @c = (2.515517, 0.802853, 0.010328);
    my @d = (1.432788, 0.189269, 0.001308);
    my $numerator = ($c[2]*$t + $c[1])*$t + $c[0];
    my $denominator = (($d[2]*$t + $d[1])*$t + $d[0])*$t + 1.0;
    return $t - $numerator / $denominator;
}


sub normal_cdf_inverse {
    my $p = $_[0];

    # See article above for explanation of this section.
    if ($p < 0.5) {
        # F^-1(p) = - G^-1(p)
        return -rational_approximation( sqrt(-2.0*log($p)) );
    } else {
        # F^-1(p) = G^-1(1-p)
        return rational_approximation( sqrt(-2.0*log(1.0-$p)) );
    }
}

1;