处理正态(高斯)分布

时间:2016-09-30 08:10:36

标签: random normal-distribution coin-flipping

我基本上坚持了相当简单的问题:

  

投掷N币并发现,其中有多少人落地

解决方案性能不能取决于N,因此我们不能只调用Math.random() < 0.5 N次。显然,有高斯分布来拯救。

我使用了Box-Muller方法:

function gaussian_random(mean, variance) {
  var s;
  var x;
  var y;
  do {
    x = Math.random() * 2.0 - 1.0;
    y = Math.random() * 2.0 - 1.0;
    s = Math.pow(x, 2) + Math.pow(y, 2);
  } while ( (s > 1) || (s == 0) );

  var gaussian = x * Math.sqrt(-2*Math.log(s)/s);
  return mean + gaussian * Math.sqrt(variance);
}

数学说,N币投掷的均值N/2方差N/4

然后,我进行了测试,将N次硬币投掷M次,给出最小,最大和平均头数。

我比较了幼稚方法(多次Math.random())和高斯Box-Muller方法的结果。

有典型的测试结果:

Toss 1000 coins, 10000 times
Straight method: 
Elapsed time: 127.330 ms
Minimum: 434
Maximum: 558
Average: 500.0306
Box-Muller method: 
Elapsed time: 2.575 ms
Minimum: 438.0112461962819
Maximum: 562.9739632480057
Average: 499.96195358695064

Toss 10 coins, 10000 times
Straight method: 
Elapsed time: 2.100 ms
Minimum: 0
Maximum: 10
Average: 5.024
Box-Muller method: 
Elapsed time: 2.270 ms
Minimum: -1.1728354576573263
Maximum: 11.169478925333504
Average: 5.010078819562535

正如我们在N = 1000上看到的那样,它几乎完全适合。

但是,N = 10 Box-Muller变得疯狂:它允许这样的测试结果,我可以得到(很少,但很有可能)10个硬币投掷11.17头! :)

毫无疑问,我做错了什么。但具体到底是什么?

source of test,并且链接到launch it

更新了x2:似乎,以前我没有很好地描述问题。它有一般版本:

  

如何在摊销的常数时间内获得 N N 均匀随机值(离散或连续)的样本均值。高斯分布对于大 N 是有效的,但有没有办法使它在小 N 上工作良好?或者 N ,解决方案应该从高斯方法切换到其他方法(例如直接)。

2 个答案:

答案 0 :(得分:2)

  

数学说,N币投掷的平均值是N / 2,方差是N / 4.

数学只说如果它是一个公平的硬币。并且没有依赖于N的解决方案。

假设所有投掷都是相互独立的,对于确切的行为,使用二项分布而不是正态分布。二项式有两个参数:N是掷硬币的数量,p是获得头部的概率(如果你愿意,则是尾部的概率)。在伪代码......

function binomial(n, p) {
  counter = 0
  successes = 0
  while counter < n {
    if Math.random() <= p
       successes += 1
    counter += 1
  }
  return successes
}

对于大N有更快的算法,但这很简单,数学上也是正确的。

答案 1 :(得分:0)

根据approved answer中讨论的内容,我找到了这个特定的解决方案。

有经验法则n*p >= 10 and n*(1-p) >= 10,但我们要定义更严格的规则。

首先,Box-Muller将被限制在[-6,6],以确保正确的结果( 640 kB应该...,我的意思是,6 sigmas应该足够每个人)。

然后,使用6常量,我们声明,为了使Box-Muller生成有效结果,Math.sqrt(variance) * 6不得超过mean。在分别使用N/2N/4作为meanvariance以及减少后,我们最终会这样做:

Math.sqrt(N) * 6 <= N

N >= 36

虽然这个条件属实,但我们可以安全地使用上限Box-Muller Gaussian。 在任何较低的样本量,坚持二项式解决方案。

在统计上检查了这条规则 - 在相对较大数量(1000万)的测试中,最小值会从样本大小32及以上的范围内停止。