Algorithm 一种二项式随机数生成算法,在n*p非常小时有效

Algorithm 一种二项式随机数生成算法,在n*p非常小时有效,algorithm,Algorithm,我需要生成二项式随机数: 例如,考虑二项式随机数。二项随机数 number是概率为p的硬币在N次投掷中的头数 在任何一次投掷中都有一个头部。如果生成N个均匀随机变量 间隔(0,1)上的数字,并计数小于p的数字,然后 计数是一个参数为N和p的二项式随机数 在我的例子中,我的N可以从1*10^3到1*10^10。我的p大约是1*10^(-7) 通常我的n*p约为1*10^(-3) 有一个简单的实现通过循环生成这样的二项式随机数: public static int getBinomial(int n

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

例如,考虑二项式随机数。二项随机数 number是概率为p的硬币在N次投掷中的头数 在任何一次投掷中都有一个头部。如果生成N个均匀随机变量 间隔(0,1)上的数字,并计数小于p的数字,然后 计数是一个参数为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;
}
public static int getBinomial(int n,双p){
int x=0;
对于(int i=0;i
这种本机实现非常慢。我尝试了在Colt()库中实现的接受-拒绝/反转方法[1]。它的速度非常快,但其生成数量的分布仅在n*p不是很小时才与本机实现一致。在我的例子中,当n*p=1*10^(-3)时,本机实现在多次运行后仍然可以生成数字1,但是接受-拒绝/反转方法永远不能生成数字1(总是返回0)

有人知道这里有什么问题吗?或者你能推荐一个更好的二项式随机数生成算法来解决我的问题吗


[1] V.Kachitvichyanukul,B.W.Schmeiser(1988):二项式随机变量生成,ACM的通信31216-222。

在np非常小的情况下,只有非常小的n值才有可能。你可以计算出这些概率,然后使用。如果你感到格外谨慎,你可以计算出某个比你准备处理的值更高的值发生的概率,然后用这个概率转移到一个特例方法,例如,生成第二个别名表以处理第一个别名方法处理的最可能的N值。

如果N*p是一个固定的小数字t,且N远大于1/t,则二项分布非常接近,它以概率e^{-t}t^k/k!返回k

下面是一些伪代码

r=e^t * RandomReal[0,1]; 
s=1;
k=0;
While[s<r, 
  (k++; s=s+t^k/k!;)]
Return k;

这不是你的@IvayloStrandjev的复制品吗?是的,是的。此问题已从mathoverflow.net迁移。是否尝试cdf方法@通常,对于离散分布来说,通常CDF反演不是一种好方法。由于离散分布的CDF是一个阶跃函数,它涉及到搜索以找到您所处的阶跃。@pjs,当然可以,但您可以使用二进制搜索,或者当np小于1时,几乎可以肯定通过搜索前几个值将找到它。我并不是说这会很快,因为我还没有尝试过,但不清楚为什么搜索会很慢。
k=0  0.9990005
k=1  0.0009990
k=2  0.0000005
k>2  1.7 * 10^{-10}