正態分佈累積函式及其反函式 C/C++
阿新 • • 發佈:2019-01-08
////////////////////////////////////////////////////////////////////////// ///////////////利用梯形法生成符合標準正態分佈的累積函from Dain////////////////// ////////////////////////////////////////////////////////////////////////// #include "iostream.h" #include "fstream.h" #include "math.h" #include "errno.h" const double PI=3.1415926; double Normal(double z) { double temp; temp=exp((-1)*z*z/2)/sqrt(2*PI); return temp; } /***************************************************************/ /* 返回標準正態分佈的累積函式,該分佈的平均值為 0,標準偏差為 1。 */ /***************************************************************/ double NormSDist(const double z) { // this guards against overflow if(z > 6) return 1; if(z < -6) return 0; static const double gamma = 0.231641900, a1 = 0.319381530, a2 = -0.356563782, a3 = 1.781477973, a4 = -1.821255978, a5 = 1.330274429; double k = 1.0 / (1 + fabs(z) * gamma); double n = k * (a1 + k * (a2 + k * (a3 + k * (a4 + k * a5)))); n = 1 - Normal(z) * n; if(z < 0) return 1.0 - n; return n; } /***************************************************************/ /* 返回標準正態分佈累積函式的逆函式。該分佈的平均值為 0,標準偏差為 1。 */ /***************************************************************/ double normsinv(const double p) { static const double LOW = 0.02425; static const double HIGH = 0.97575; /* Coefficients in rational approximations. */ static const double a[] = { -3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02, 1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00 }; static const double b[] = { -5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02, 6.680131188771972e+01, -1.328068155288572e+01 }; static const double c[] = { -7.784894002430293e-03, -3.223964580411365e-01, -2.400758277161838e+00, -2.549732539343734e+00, 4.374664141464968e+00, 2.938163982698783e+00 }; static const double d[] = { 7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00 }; double q, r; errno = 0; if (p < 0 || p > 1) { errno = EDOM; return 0.0; } else if (p == 0) { errno = ERANGE; return -HUGE_VAL /* minus "infinity" */; } else if (p == 1) { errno = ERANGE; return HUGE_VAL /* "infinity" */; } else if (p < LOW) { /* Rational approximation for lower region */ q = sqrt(-2*log(p)); return (((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1); } else if (p > HIGH) { /* Rational approximation for upper region */ q = sqrt(-2*log(1-p)); return -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) / ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1); } else { /* Rational approximation for central region */ q = p - 0.5; r = q*q; return (((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q / (((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1); } } void main() { ofstream out1; out1.open("正態分佈累積函式.xls"); for(int i=0;i<1200;i++) out1<<(-6)+i*0.01<<"\t"<<NormSDist((-6)+i*0.01)<<"\n"; out1.close(); out1.open("正態分佈累積函式的逆函式.xls"); for(i=0;i<1000;i++) out1<<0.001*i<<"\t"<<normsinv(0.001*i)<<"\n"; out1.close(); }