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

时间:2009-08-06 21:20:14

标签: java math probability random poisson

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

我找到了this page,在最后一段中说:

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

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

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

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

5 个答案:

答案 0 :(得分:39)

泊松分布

这是how Wikipedia says Knuth says to do it

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

二项分布

按照Non-Uniform Random Variate Generation (PDF)的第10章由Luc Devroye(我发现从the Wikipedia article链接)给出了这个:

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)。根据这些值通常的大小以及调用生成器的频率,您可能需要更好的算法。我上面链接的论文有更复杂的算法,它们在恒定的时间内运行,但我会将这些实现作为练习留给读者。 :)

答案 1 :(得分:3)

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

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

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

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

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

答案 2 :(得分:2)

虽然Kip发布的答案对于生成具有较小到达率(λ)的Poisson RV非常有效,但由于数值稳定性,维基百科Generating Poisson Random variables中发布的第二种算法对于较大的到达率更好。

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

答案 3 :(得分:1)

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

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

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

此致

答案 4 :(得分:1)

您可以将其添加到build.gradle

implementation 'org.kie.modules:org-apache-commons-math:6.5.0.Final'

并使用类 PoissonDistribution more detail for class PoissonDistribution