Реализации нормального CDF, приведенные здесь, представляют собой аппроксимации одинарной точности , в которых float
заменены на double
и, следовательно, точны только до 7 или 8 значащих (десятичных) цифр.
Для реализации VB приближения двойной точности Харта см. Рис. 2 из лучшего приближения Запада к кумулятивным нормальным функциям .
Редактировать : Мой перевод реализации Уэста на C ++:
double
phi(double x)
{
static const double RT2PI = sqrt(4.0*acos(0.0));
static const double SPLIT = 7.07106781186547;
static const double N0 = 220.206867912376;
static const double N1 = 221.213596169931;
static const double N2 = 112.079291497871;
static const double N3 = 33.912866078383;
static const double N4 = 6.37396220353165;
static const double N5 = 0.700383064443688;
static const double N6 = 3.52624965998911e-02;
static const double M0 = 440.413735824752;
static const double M1 = 793.826512519948;
static const double M2 = 637.333633378831;
static const double M3 = 296.564248779674;
static const double M4 = 86.7807322029461;
static const double M5 = 16.064177579207;
static const double M6 = 1.75566716318264;
static const double M7 = 8.83883476483184e-02;
const double z = fabs(x);
double c = 0.0;
if(z<=37.0)
{
const double e = exp(-z*z/2.0);
if(z<SPLIT)
{
const double n = (((((N6*z + N5)*z + N4)*z + N3)*z + N2)*z + N1)*z + N0;
const double d = ((((((M7*z + M6)*z + M5)*z + M4)*z + M3)*z + M2)*z + M1)*z + M0;
c = e*n/d;
}
else
{
const double f = z + 1.0/(z + 2.0/(z + 3.0/(z + 4.0/(z + 13.0/20.0))));
c = e/(RT2PI*f);
}
}
return x<=0.0 ? c : 1-c;
}
Обратите внимание, что я переставил выражения в более привычные формы для приближений рядов и непрерывных дробей. Последнее магическое число в коде Уэста - это квадратный корень из 2 & pi;, который я отложил до компилятора в первой строке, используя идентификатор acos (0) = & frac12; & Пи;.
Я трижды проверил магические числа, но всегда есть вероятность, что я что-то опечатал. Если вы обнаружили опечатку, пожалуйста, прокомментируйте!
Результаты тестовых данных, которые Джон Кук использовал в своем ответе,
x phi Mathematica
-3 1.3498980316301150e-003 0.00134989803163
-1 1.5865525393145702e-001 0.158655253931
0 5.0000000000000000e-001 0.5
0.5 6.9146246127401301e-001 0.691462461274
2.1 9.8213557943718344e-001 0.982135579437
Мне немного не по себе от того, что они согласны со всеми цифрами, приведенными для результатов Mathematica.