相关问题是: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。
答案 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.