I'm trying to convert something from my excel spreadsheets into Javascript and came along the NORMSINV() macro in my spreadsheets.
The NormSInv() is nicely documented at http://office.microsoft.com/en-us/excel-help/normsinv-HP005209195.aspx. Basically it's of the form
Z = NormSInv(probability) where if you give it the probability (say 0.90), it gives you the Z value for a standard normal distribution (Z= 1.33).
I could encode the entire transformation table as per http://en.wikipedia.org/wiki/Standard_normal_table but want to avoid reinventing the wheel.
So, is there such a function in Javascript? eg. in Javascript's math libraries (if there is such a thing!).
Thanks
Sid
I ended up implementing the NormSInv() in javascript myself. No point in including an entire stats library when I need just one function
function NormSInv(p) {
var a1 = -39.6968302866538, a2 = 220.946098424521, a3 = -275.928510446969;
var a4 = 138.357751867269, a5 = -30.6647980661472, a6 = 2.50662827745924;
var b1 = -54.4760987982241, b2 = 161.585836858041, b3 = -155.698979859887;
var b4 = 66.8013118877197, b5 = -13.2806815528857, c1 = -7.78489400243029E-03;
var c2 = -0.322396458041136, c3 = -2.40075827716184, c4 = -2.54973253934373;
var c5 = 4.37466414146497, c6 = 2.93816398269878, d1 = 7.78469570904146E-03;
var d2 = 0.32246712907004, d3 = 2.445134137143, d4 = 3.75440866190742;
var p_low = 0.02425, p_high = 1 - p_low;
var q, r;
var retVal;
if ((p < 0) || (p > 1))
{
alert("NormSInv: Argument out of range.");
retVal = 0;
}
else if (p < p_low)
{
q = Math.sqrt(-2 * Math.log(p));
retVal = (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / ((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
}
else if (p <= p_high)
{
q = p - 0.5;
r = q * q;
retVal = (((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q / (((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1);
}
else
{
q = Math.sqrt(-2 * Math.log(1 - p));
retVal = -(((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / ((((d1 * q + d2) * q + d3) * q + d4) * q + 1);
}
return retVal;
}
There's nothing that I know of embedded into JavaScript's core.
You might like to take a look at the JStat JavaScript library. This seems to offer a range of functions for statistical calculation.
i extracted the jStat.distribution.normal.inv
into a standalone function you can use with webpack as a closure (or just by itself).
import normalinv from 'jsfile'
let yourMath = normalinv()
or
var yourMath = normalinv();
yourMath(p, m, d)
export default function normalinv() {
function erfcinv(p) {
var j = 0;
var x, err, t, pp;
if (p >= 2)
return -100;
if (p <= 0)
return 100;
pp = (p < 1) ? p : 2 - p;
t = Math.sqrt(-2 * Math.log(pp / 2));
x = -0.70711 * ((2.30753 + t * 0.27061) /
(1 + t * (0.99229 + t * 0.04481)) - t);
for (; j < 2; j++) {
err = erfc(x) - pp;
x += err / (1.12837916709551257 * Math.exp(-x * x) - x * err);
}
return (p < 1) ? x : -x;
}
function erfc(x) {
return 1 - erf(x);
}
function erf(x) {
var cof = [-1.3026537197817094, 6.4196979235649026e-1, 1.9476473204185836e-2,
-9.561514786808631e-3, -9.46595344482036e-4, 3.66839497852761e-4,
4.2523324806907e-5, -2.0278578112534e-5, -1.624290004647e-6,
1.303655835580e-6, 1.5626441722e-8, -8.5238095915e-8,
6.529054439e-9, 5.059343495e-9, -9.91364156e-10,
-2.27365122e-10, 9.6467911e-11, 2.394038e-12,
-6.886027e-12, 8.94487e-13, 3.13092e-13,
-1.12708e-13, 3.81e-16, 7.106e-15,
-1.523e-15, -9.4e-17, 1.21e-16,
-2.8e-17
];
var j = cof.length - 1;
var isneg = false;
var d = 0;
var dd = 0;
var t, ty, tmp, res;
if (x < 0) {
x = -x;
isneg = true;
}
t = 2 / (2 + x);
ty = 4 * t - 2;
for (; j > 0; j--) {
tmp = d;
d = ty * d - dd + cof[j];
dd = tmp;
}
res = t * Math.exp(-x * x + 0.5 * (cof[0] + ty * d) - dd);
return isneg ? res - 1 : 1 - res;
}
return function inv(p, mean, std) {
return -1.41421356237309505 * std * erfcinv(2 * p) + mean;
}
}