生成泊松和二项式随机数的算法?

我一直在四处寻找,但我不知道该怎么办。

我发现这个页面在最后一段中说:

使用这个简单的配方获得从泊松分布中获取的随机数的简单生成器:如果x 1 ,x 2 ,…是在0和1之间具有均匀分布的随机数序列,则k是第一个整数,其中乘积x 1 ·x 2 ·……·x k + 1 <e

我发现了另一个描述如何生成二项式数的页面 ,但我认为它使用的是泊松生成的近似值,这对我没有帮助。

例如,考虑二项式随机数。 二项式随机数是硬币N次投掷中的头数,其中任意一次投掷的头部概率为p。 如果在区间(0,1)上生成N个均匀随机数并计算小于p的数,则计数是具有参数N和p的二项式随机数。

我知道有库可以做到这一点,但我不能使用它们,只能使用语言提供的标准统一生成器(在本例中为java)。

泊松分布

以下是维基百科说Knuth所说的 :

init: Let L ← e^(−λ), k ← 0 and p ← 1. do: k ← k + 1. Generate uniform random number u in [0,1] and let p ← p × u. while p > L. return k − 1. 

在Java中,那将是:

 public static int getPoisson(double lambda) { double L = Math.exp(-lambda); double p = 1.0; int k = 0; do { k++; p *= Math.random(); } while (p > L); return k - 1; } 

二项分布

通过Luc Devroye的非均匀随机变量生成 (PDF)的第10章(我发现维基百科的文章链接)给出了这样的结论:

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

请注意

这些算法都不是最佳的。 第一个是O(λ),第二个是O(n)。 根据这些值通常的大小以及调用生成器的频率,您可能需要更好的算法。 我上面链接的论文有更复杂的算法,它们在恒定的时间内运行,但我会将这些实现作为练习留给读者。 🙂

对于这个和其他数值问题,圣经是数字食谱书。

这里有一个免费的C版本: http : //www.nrbook.com/a/bookcpdf.php (需要插件)

或者您可以在Google图书上看到它: http : //books.google.co.uk/books?id = 4t-sybVuoqoC&ltg = PP1 &ots = 5IhMINLhHo&dq = numju%20recipes%20in%20c&PP = PP1#v = onepage&q =&f = false

C代码应该很容易转移到Java。

对于许多数值问题,这本书值得用金重。 在上面的网站上,您还可以购买该书的最新版本。

虽然Kip发布的答案对于生成具有较小到达率(λ)的泊松RV是完全有效的,但是维基百科生成泊松随机变量中发布的第二种算法由于数值稳定性而对于较大的到达率更好。

在实施其中一个需要生成具有非常高λ的Poisson RV的项目期间,我遇到了问题。 所以我建议另一种方式。

CERN在以下库中有几种实现(Java代码):

http://acs.lbl.gov/~hoschek/colt/

关于二项式随机数,它基于1988年“二项式随机变量生成”的论文,我建议你使用优化算法。

问候