我需要生成二项式随机数:
例如,考虑二项式随机数。二项式随机 number是硬币N次投掷的头数,概率为p 在任何一个投掷的头上。如果你生成N均匀随机 在区间(0,1)上的数字,并计算小于p的数字,然后 count是带有参数N和p的二项式随机数。
在我的情况下,我的N可以从1 * 10 ^ 3到1 * 10 ^ 10。我的p大约是1 * 10 ^( - 7)。
我的n * p通常大约是1 * 10 ^( - 3)。
通过循环生成这样的二项式随机数有一个简单的实现:
public static int getBinomial(int n, double p) {
int x = 0;
for(int i = 0; i < n; i++) {
if(Math.random() < p)
x++;
}
return x;
}
这种原生实现非常慢。我尝试了在Colt(http://acs.lbl.gov/software/colt/)lib中实现的Acceptance Rejection / Inversion方法[1]。它非常快,但是当n * p不是很小时,它生成的数字的分布仅与本机实现一致。在我的情况下,当n * p = 1 * 10 ^( - 3)时,本机实现仍然可以在多次运行后生成数字1,但是Acceptance Rejection / Inversion方法永远不会生成数字1(始终返回0)。
有谁知道这里有什么问题?或者你能否提出一个更好的二项式随机数生成算法来解决我的问题。
[1] V. Kachitvichyanukul,B.W。 Schmeiser(1988):二项式随机变量生成,ACM通讯31,216-222。
答案 0 :(得分:1)
如果n * p是固定的小数t,并且n远大于1 / t,则二项分布非常接近Poisson distribution,其以概率e ^ { - t}返回k吨^ K /ķ!
这是一些伪代码
r=e^t * RandomReal[0,1];
s=1;
k=0;
While[s<r,
(k++; s=s+t^k/k!;)]
Return k;
如果t真的很小,那么很难区分这个和一个例程,它只返回0概率1-t和t其余时间。例如,如果t = 0.001且n很大,则各种k值的概率为
k=0 0.9990005
k=1 0.0009990
k=2 0.0000005
k>2 1.7 * 10^{-10}
答案 1 :(得分:0)
当np非常小时,只有非常小的n值才有可能。您可以计算出那些概率,然后使用http://en.wikipedia.org/wiki/Alias_method。如果您感觉更加谨慎,那么您可以计算出某些值高于您准备处理的值的概率,并转移到具有此概率的特殊情况方法,例如生成第二个别名表以应对最多可能N值高于你的第一个别名方法应对的。