Это реализация грубой силы, но с точностью до цифры.Приведенное выше приближение является точным в пределах 10 ^ -7.Моя реализация работает медленнее (700 наносекунд), но с точностью до 10 ^ -14.normal (25,30,1.4241) === 0.00022322110257305683, против 0,000223221102572082 Вольфрама.
Он принимает степенной ряд стандартного нормального pdf, то есть колоколообразной кривой, а затем интегрирует ряд.
Я изначально написал это в C, поэтому я допускаю, что некоторые оптимизации могут показаться глупыми в Javascript.
function normal(x, mu, sigma) {
return stdNormal((x-mu)/sigma);
}
function stdNormal(z) {
var j, k, kMax, m, values, total, subtotal, item, z2, z4, a, b;
// Power series is not stable at these extreme tail scenarios
if (z < -6) { return 0; }
if (z > 6) { return 1; }
m = 1; // m(k) == (2**k)/factorial(k)
b = z; // b(k) == z ** (2*k + 1)
z2 = z * z; // cache of z squared
z4 = z2 * z2; // cache of z to the 4th
values = [];
// Compute the power series in groups of two terms.
// This reduces floating point errors because the series
// alternates between positive and negative.
for (k=0; k<100; k+=2) {
a = 2*k + 1;
item = b / (a*m);
item *= (1 - (a*z2)/((a+1)*(a+2)));
values.push(item);
m *= (4*(k+1)*(k+2));
b *= z4;
}
// Add the smallest terms to the total first that
// way we minimize the floating point errors.
total = 0;
for (k=49; k>=0; k--) {
total += values[k];
}
// Multiply total by 1/sqrt(2*PI)
// Then add 0.5 so that stdNormal(0) === 0.5
return 0.5 + 0.3989422804014327 * total;
}