【问题标题】:Algorithm to generate Poisson and binomial random numbers?生成泊松和二项式随机数的算法?
【发布时间】:2010-11-17 12:18:58
【问题描述】:

我一直在环顾四周,但我不知道该怎么做。

我发现 this page 在最后一段中说:

一个简单的从泊松分布中提取的随机数生成器是使用这个简单的配方获得的:如果 x1, x2, ... 是零和一之间均匀分布的随机数序列,k 是 x1 · x2 · ... · xk 乘积的第一个整数+1

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

例如,考虑二项式随机数。二项式随机数是在 N 次投掷硬币中正面的数量,其中任何一次抛硬币的正面概率为 p。如果在区间(0,1)上生成N个均匀随机数,对小于p的数进行计数,则计数为参数为N和p的二项式随机数。

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

【问题讨论】:

  • Numerical Recipes (3rd Edition) 这本书对生成泊松和二项式偏差有完整的解释
  • 其他一些可用的库提供here:

标签: java math probability random poisson


【解决方案1】:

泊松分布

这里是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;
}

二项分布

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

【讨论】:

  • @Kip 在你的第一个例子中,L 代表 Lambda,P 代表什么?
  • @AkshatAgarwal 实际上 L 代表 e^(−lambda)。 p 只是一个介于 0 和 1 之间的数字。在每次迭代时,它都会减少一个随机量(当它乘以一个介于 0 和 1 之间的随机数时),直到达到 p 小于 L 的点。 lambda 是,L 将越小(接近 0),这意味着在 p 小于 L 之前,我们将平均经历的循环迭代次数越多。
  • lambda 有限制吗?当我通过 1000 或 2000 时,我的结果平均为 745。如果我通过较低的数字,结果似乎是正确的。
【解决方案2】:

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

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

或者你可以在谷歌图书上看到它: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。

对于许多数值问题,这本书物超所值。您还可以在上述网站上购买该书的最新版本。

【讨论】:

  • 数字食谱书不是免费的。您需要密码才能解锁 PDF 文件。
【解决方案3】:

虽然 Kip 发布的答案对于生成具有小到达率 (lambda) 的泊松 RV 是完全有效的,但由于数值稳定性,Wikipedia Generating Poisson Random variables 中发布的第二种算法对于较大的到达率更好。

由于这个原因,我在执行需要生成具有非常高 lambda 的 Poisson RV 的项目之一时遇到了问题。所以我建议另一种方式。

【讨论】:

    【解决方案4】:

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

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

    关于二项式随机数,它基于 1988 年的论文“二项式随机变量生成”,我向您推荐该论文,因为他们使用了优化的算法。

    问候

    【讨论】:

      【解决方案5】:

      你可以把它添加到 build.gradle

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

      并使用类 PoissonDistribution more detail for class PoissonDistribution

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-28
        • 2011-06-26
        • 2012-03-12
        • 2016-01-31
        • 2016-07-31
        • 1970-01-01
        相关资源
        最近更新 更多