当n * p非常小时,二项式随机数生成算法

时间:2014-05-10 08:44:42

标签: algorithm

我需要生成二项式随机数:

  

例如,考虑二项式随机数。二项式随机   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。

2 个答案:

答案 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值高于你的第一个别名方法应对的。