confidence_intervals.c

来自「置信区间的相关程序」· C语言 代码 · 共 197 行

C
197
字号
/* confidence_intervals.c * * Author:       Jon Hamkins * Date:         Tue Dec 11 09:45:02 PST 2001 * Language:     ANSI C * Last Revised: Tue Dec 11 11:32:41 PST 2001 * * Functions to compute confidence intervals.  Given x events occuring * in N tries, compute the 95% (or other) confidence interval, assuming * one of * * (1) a binomial distribution, useful when the events occur * independently at discrete times, or * * (2) a Poisson distribution, useful when the arrival times occur * independently (in continuous time), or as an approximation to a * binomial distribution when N->oo, x->constant. * * (3) a Gaussian distribution, useful as an approximation of binomial * distribution when N->oo and x/N->constant.  Accurate when the number * of trials is large. * * For example, the 95% confidence interval assuming a Gaussian * distribution for b errors in N simulated bits is the interval * (gaussian_low(b,N,0.025), gaussian_high(b,N,0.025)). * * Refs:  * * Stark & Woods "Probability, Random Processes, and Estimation * Theory for Engineers" * * http://members.aol.com/johnp71/confint.html * */#include <math.h>#define EPS (0.000001)#define TOOBIG (1e30)/* Compute probability of at least x1 successes, and no more than x2 * successes, in N tries from a binomial distribution with population * proportion p. */doublebinomial_p(double N, double p, double x1, double x2){   double q, k = 0., v = 1., s = 0., tot = 0.;   q = p / (1. - p);   while (k <= N) {      tot += v;      if ((k >= x1) && (k <= x2)) s += v;      if (tot > TOOBIG) {         s /= TOOBIG;         tot /= TOOBIG;         v /= TOOBIG;      }      k++;      v *= q * (N + 1 - k) / k;   }   return(s/tot);}/* Perform binary search to find lower confidence interval, for binomial * distribution */double binomial_low(double vx, double vN, double p){   double vP, v, vsL = 0., vsH;   vP = vx / vN;   v = 0.5 * vP;   vsH = vP;   while ((vsH - vsL) > EPS) {      if (binomial_p(vN, v, vx, vN) > p) {         vsH = v;         v = 0.5 * (vsL + v);      }      else {         vsL = v;         v = 0.5 * (v + vsH);      }   }   return(v);}/* Perform binary search to find upper confidence interval, for binomial * distribution */doublebinomial_high(double vx, double vN, double p) {   double vP, v, vsL, vsH = 1.;   vP = vx / vN;   v = 0.5 * (1. + vP);   vsL = vP;   while ((vsH - vsL) > EPS) {      if (binomial_p(vN, v, 0., vx) < p) {         vsH = v;         v = 0.5 * (vsL + v);      }      else {         vsL = v;         v = 0.5 * (v + vsH);      }   }   return(v);}/* Compute probability of at least x1 successes, and no more than x2 * successes, from a Poisson distribution, given z successes observed. */doublepoisson_p(double z, double x1, double x2){   double q=1, tot=0, s=0, k=0;   while ((k <= z) || (q > tot * 0.0000000001)) {      tot += q;      if ((k >= x1) && (k <= x2)) s += q;      if (tot > TOOBIG) {         s /= TOOBIG;         tot /= TOOBIG;         q /= TOOBIG;      }      k++;      q *= z / k;   }   return(s / tot);}/* Perform binary search to find lower confidence interval, for Poisson * distribution */doublepoisson_low(double vz, double p){   double v = 0.5, dv = 0.5;   while (dv > 0.0000001) {      dv *= 0.5;      if (poisson_p((1 + vz) * v / (1 - v), vz, 10000000000) > p)         v -= dv;      else v += dv;   }   return((1.+vz)*v/(1.-v));}/* Perform binary search to find higher confidence interval, for Poisson * distribution */doublepoisson_high(double vz, double p){   double v=0.5, dv=0.5;   while (dv > 0.0000001) {    dv *= 0.5;    if (poisson_p((1 + vz) * v / (1 - v), 0, vz) < p)        v -= dv;        else v += dv;   }   return((1 + vz) * v / (1 - v));}/* Find lower confidence interval, for Gaussian approximation to * binomial distribution.  (A binomial r.v. is a sum of Bournoulli * r.v.'s, and by central limit theorem, a sum with many terms * approaches a Gaussian r.v. with mean equal to the sum.)  */double gaussian_low(double vx, double vN, double p){   double low, med, high, mean, var;   mean = vx;   var = vx*(1-vx/vN);   low = -1000.;   med = 0.5 * vx;   high = vx;   while ((high - low) > EPS) {      if (0.5+0.5*erf(M_SQRT1_2*(med-mean)/sqrt(var)) > p) {         high = med;         med = 0.5 * (low + med);      }      else {         low = med;         med = 0.5 * (med + high);      }   }   return(med/vN);}/* Find upper confidence interval (by symmetry about mean) */doublegaussian_high(double vx, double vN, double p) {   return(2*vx/vN-gaussian_low(vx,vN,p));}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?