C / C ++中的累积正态分布函数
我想知道是否有math库中的统计function,这些math库是Cmath等标准C ++库的一部分。 如果没有,你们可以推荐一个好的统计资料库,它具有累积的正态分布函数吗? 提前致谢。
更具体地说,我期待使用/创build一个累积分布函数。
以下是14行代码中的累积正态分布的独立C ++实现。
Theres不是直接的function。 但是由于高斯误差函数及其互补函数与正态累积分布函数有关(参见这里 ),我们可以使用实现的c函数erfc
:
double normalCFD(double value) { return 0.5 * erfc(-value * M_SQRT1_2); }
我用它来进行统计计算,而且效果很好。 不需要使用系数。
提升是一样好的标准:D在这里你去: 提高math/统计 。
我想出了如何使用gsl来完成这个任务,在之前的回答中,我find了一个非库解决scheme(希望这可以帮助那些像我一样寻找它的人):
#ifndef Pi #define Pi 3.141592653589793238462643 #endif double cnd_manual(double x) { double L, K, w ; /* constants */ double const a1 = 0.31938153, a2 = -0.356563782, a3 = 1.781477937; double const a4 = -1.821255978, a5 = 1.330274429; L = fabs(x); K = 1.0 / (1.0 + 0.2316419 * L); w = 1.0 - 1.0 / sqrt(2 * Pi) * exp(-L *L / 2) * (a1 * K + a2 * K *K + a3 * pow(K,3) + a4 * pow(K,4) + a5 * pow(K,5)); if (x < 0 ){ w= 1.0 - w; } return w; }
这里给出的正常CDF的实现是单精度近似,其中float
已经被double
float
替代,因此仅精确到7或8个重要(十进制)数字。
对于Hart的双精度逼近的VB实现,请参见West's Better对累积正态函数的近似值图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; }
请注意,我已经将expression式重新排列为更为熟悉的forms,用于序列和连续分数近似。 West代码中的最后一个幻数是2π的平方根,我通过利用身份acos(0)= 1 /2π推迟到编译器的第一行。
我已经三次检查了魔术数字,但总是有错误input的机会。 如果您发现错字,请发表评论!
John Cook在答案中使用的testing数据的结果是
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结果的所有数字的事实中得到一些小小的安慰。
来自NVIDIA CUDA样品:
static double CND(double d) { const double A1 = 0.31938153; const double A2 = -0.356563782; const double A3 = 1.781477937; const double A4 = -1.821255978; const double A5 = 1.330274429; const double RSQRT2PI = 0.39894228040143267793994605993438; double K = 1.0 / (1.0 + 0.2316419 * fabs(d)); double cnd = RSQRT2PI * exp(- 0.5 * d * d) * (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5))))); if (d > 0) cnd = 1.0 - cnd; return cnd; }
版权所有1993-2012 NVIDIA公司。 版权所有。