C#:从二项分布生成数字的数值算法

我需要从二项式(n,p)分布生成随机数。

二项式(n,p)随机变量是n个均匀变量的总和,其中概率为1。 在伪代码中, x=0; for(i=0; i<n; ++i) x+=(rand()<p?1:0); x=0; for(i=0; i<n; ++i) x+=(rand()<p?1:0); 将生成二项式(n,p)。

我需要为小的和非常大的n生成这个,例如n = 10 ^ 6和p = 0.02。 是否有任何快速数值算法来生成它?

编辑 –

现在这是我的近似值(以及精确泊松和正态分布的函数) –

  public long Binomial(long n, double p) { // As of now it is an approximation if (n < 1000) { long result = 0; for (int i=0; i<n; ++i) if (random.NextDouble() < p) result++; return result; } if (n * p < 10) return Poisson(n * p); else if (n * (1 - p) < 10) return n - Poisson(n * p); else { long v = (long)(0.5 + nextNormal(n * p, Math.Sqrt(n * p * (1 - p)))); if (v  n) v = n; return v; } } 

如果您愿意付费,请查看Centerspace的NMath。

否则,Stats程序R使用的C代码就在这里 ,并且应该直接移植到C#。

编辑:在Jack Xu的C#实用数值方法的 p178上有关于创建方法的细节(包括代码)。

另一个编辑: 一个免费的C#库 ,可以满足您的需求。

另一种选择是从正常或泊松中采样,然后添加Metropolis-Hastings步骤来接受或拒绝您的样本。 如果您接受完成,如果拒绝,则必须再次完全重新取样。 我的猜测是因为近似值非常接近,所以你几乎总会得到一个接受步骤,偶尔你会拒绝。

Luc Devroye的书也有一些很好的二项式采样算法。

PS如果你最终得到一个好的算法; 你介意在Math.Net Numerics上分享吗?

没有明显的方法可以有效地做到这一点。 对于小n,您可能只是我们计算逆PDF的公式。 对于较大的n,您可能最好使用其中一个更容易计算的分布的近似值 。