duk*_*ave 3 c++ math excel function magic-numbers
在寻找Excel NORMDIST(累积)函数的C++实现时,我在网站上找到了这个:
static double normdist(double x, double mean, double standard_dev)
{
double res;
double x=(x - mean) / standard_dev;
if (x == 0)
{
res=0.5;
}
else
{
double oor2pi = 1/(sqrt(double(2) * 3.14159265358979323846));
double t = 1 / (double(1) + 0.2316419 * fabs(x));
t *= oor2pi * exp(-0.5 * x * x)
* (0.31938153 + t
* (-0.356563782 + t
* (1.781477937 + t
* (-1.821255978 + t * 1.330274429))));
if (x >= 0)
{
res = double(1) - t;
}
else
{
res = t;
}
}
return res;
}
Run Code Online (Sandbox Code Playgroud)
我有限的数学知识让我想到泰勒系列,但我无法确定这些数字的来源:
0.2316419,
0.31938153,
-0.356563782,
1.781477937,
-1.821255978,
1.330274429
任何人都可以建议他们来自哪里,以及如何衍生出来?
查看数字配方,第6.2.2章.近似值是标准的.回想起那个
NormCdf(x) = 0.5 * (1 + erf(x / sqrt(2)))
erf(x) = 2 / (sqrt(pi)) integral(e^(-t^2) dt, t = 0..x)
Run Code Online (Sandbox Code Playgroud)
写erf作为
1 - erf x ~= t * exp(-x^2 + P(t))
Run Code Online (Sandbox Code Playgroud)
对于正x,在哪里
t = 2 / (2 + x)
Run Code Online (Sandbox Code Playgroud)
由于t在0和1之间,你可以一次性找到P by Chebyshev近似(Numerical Recipes,5.8节).你没有使用泰勒展开:你希望近似在整个实线上是好的,泰勒展开不能保证.切比雪夫近似是L ^ 2范数中的最佳多项式近似,这是非常难以找到的极小极大多项式的良好替代(=支持范数中的最佳多项式近似).
这里的版本略有不同.相反,一个人写道
1 - erf x = t * exp(-x^2) * P(t)
Run Code Online (Sandbox Code Playgroud)
但过程类似,并且直接计算normCdf,而不是erf.
特别地,非常类似地,您使用的"实现"与文本中处理的实现有所不同,因为它具有形式,b*exp(-a*z^2)*y(t)但它也是Chevishev约.你可以在Schonfelder(1978)的论文中看到erfc(x)函数[ http://www.ams.org/journals/mcom/1978-32-144/S0025-5718-1978-0494846-8/ S0025-5718-1978-0494846-8.pdf ]
同样在Numerical Recipes第3版中,在6.2.2章的最后,它们提供了非常精确的类型的C实现 t*exp(-z^2 + c0 + c1*t+ c2t^2 + c3*t^3 + ... + c9t^9)