Java中有效的二项式随机数生成器代码

时间:2014-05-09 09:50:32

标签: java algorithm random

相关问题是:Algorithm to generate Poisson and binomial random numbers?

我只是对二项式随机数进行描述:

  

例如,考虑二项式随机数。二项式随机   number是硬币N次投掷的头数,概率为p   在任何一个投掷的头上。如果你生成N均匀随机   在区间(0,1)上的数字,并计算小于p的数字,然后   count是带有参数N和p的二项式随机数。

使用迭代在Algorithm to generate Poisson and binomial random numbers?中有一个简单的解决方案:

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;
}

然而,我追求二项式随机数生成器的目的只是为了避免低效的循环(i从0到n)。我的n可能非常大。 p通常非常小。

我的案例的玩具示例可能是:n = 1 * 10 ^ 6,p = 1 * 10 ^( - 7)。

n的范围可以从1 * 10 ^ 3到1 * 10 ^ 10。

2 个答案:

答案 0 :(得分:7)

如果您的p值很小,那么您会比您引用的天真实施更喜欢这个值。它仍然循环,但预期的迭代次数为O(np),因此它对于小p值来说非常快。如果您正在使用较大的p值,请将p替换为q = 1-p,并从n中减去返回值。显然,p = q = 0.5时会出现最糟糕的情况。

public static int getBinomial(int n, double p) {
   double log_q = Math.log(1.0 - p);
   int x = 0;
   double sum = 0;
   for(;;) {
      sum += Math.log(Math.random()) / (n - x);
      if(sum < log_q) {
         return x;
      }
      x++;
   }
}

实施是Luc Devroye&#34; Second Waiting Time Method&#34;在他的文本的第522页&#34;非一致随机变量生成。&#34;

基于接受/拒绝技术的方法更快,但实施起来要复杂得多。

答案 1 :(得分:0)

我可以想象一种通过常数因子加速它的方法(例如4)。

投掷4次后,你将投掷头部0,1,2,3或4。

它的概率类似于[0.6561,0.2916,0.0486,0.0036,0.0001]。

现在您可以生成一个数字随机数并模拟4个原始投掷。如果不清楚我怎么能详细说明一点。

这种方式经过一些原始的预先计算后,你可以将这个过程加速几乎4次。它要求精确的唯一要求是随机生成器的粒度至少为p ^ 4.