通过添加随机数来近似正态分布

Approximating Normal Distribution by adding Random Numbers

我想生成一些正态分布的随机数。它不是关键任务,因此一个简单的算法就足够了。然后我想提供我自己的均值和标准差。

据我所知,根据中心极限定理,我应该能够通过将随机数相加来近似正态分布的随机数。

例如:

rand()+rand()+rand()+rand()+rand()+rand()

其中 rand() 产生从 0 到 1 的均匀分布的随机数 是一个合理的近似值。 (我知道技术上是 0 ≤ rand() < 1)。

预期的均值是 6*0.5 所以我用这样的东西得到了期望的均值:

(rand()+rand()+rand()+rand()+rand()+rand()-3) + mean

但是标准偏差是多少?

一旦我知道了,设置一个任意的标准差是否只是乘法的问题?

更新

通过实验,我发现

(rand()+rand()+rand()+rand()+rand()+rand()-3)*sqrt(2)*sd+mean

给了我一组具有所需标准差和平均值的数据。我已经在具有 1000 万行的数据库 (PostgreSQL) 中使用 stddev()avg() 聚合函数对此进行了测试,典型结果接近小数点后 2 位,这还不错。

我不知道为什么要涉及 sqrt(2) ......

解决方案

好的,感谢下面的 Severin Pappadeux,我有了答案。

我可以通过以下方式生成合理的结果:

(rand() + … + rand() - n/2) / sqrt(n/12) * sd + mean

其中 n 是我准备拨打的 rand() 个电话的数量。

标准差定义如下:

迭代 N 值,表示为 xi,并使用平均值 (xbar)。一些 JavaScript 伪代码看起来像:

var values = [...];
for(var i = 0, var mean; i < values.length; i++) {
   mean += values[i];
}
mean /= values.length;
for(var i = 0, var standardDev; i < values.length) {
   standardDev += Math.pow(values[i] - mean, 2);
}
standardDev = Math.sqrt(standardDev / (values.length - 1));

理论上,好的 RNG 应该以非常平坦的方式偏离,表明 RNG 范围内所有值的可能性均等。

如果你使用Python,你可以使用[numpy][1]

import numpy
numpy.random.randn()

From what I have been able to read, according to the Central Limit Theorem, I should be able to approximate normally distributed random numbers by adding random numbers together.

这是正确的做法。唯一的问题是仔细分析你错过的尾巴。

让我们考虑制作 N(0,1) - 均值为 0 且 std.deviation 为 1 的高斯分布。然后任何其他高斯分布 N(\mu, \sigma) 只是缩放并从 N(0,1) 偏移。

因此,G(0,1)N(0,1) 的近似值)的建议算法是

G(0,1) = U(0,1) + U(0,1) + U(0,1) + U(0,1) + U(0,1) + U(0,1)

其中 U(0,1) 是 [0,1) 范围内的 uniformly distributed random number。让我们看看均值。

E(G(0,1)) = 6*E(U(1,0)) = 6*0.5 = 3

这正是您所拥有的。因此,要获得 G(0,1) 的 0 均值,我们必须减去 3。现在让我们检查 G(0,1) 的方差,我们必须使其等于 1.

V(G(0,1)) = 6*V(U(1,0)) = 6*(1/12) = 1/2

Std.deviation (σ) 是方差的平方根,所以要得到它,你必须除以 sqrt(1/2)。

因此,最终表达式将是

G(0,1) = (U(0,1) + U(0,1) + U(0,1) + U(0,1) + U(0,1) + U(0,1) - 3)/sqrt(1/2)

并且它是 N(0,1).

的相当好的近似值

I have no idea why sqrt(2) is involved …

除以 sqrt(1/2) 与乘以 sqrt(2) 相同 - 现在我希望您知道它的来源。

一些简单的推论 - 对于其他一些 n U(0,1) 方差乘数的总和将包括项 sqrt(n/12).

另一个简单的推论-因为V(U(0,1))等于1/12,所以对12个U(0,1)求和不需要任何乘数

G(0,1) = Sum_1^12 U(0,1) - 6

实际上在一些旧的采样食谱中经常被引用books/papers。

您可能还想看看相关的 Irwin-Hall distribution and Bates distribution

更新

我考虑过对该方法进行一些简化。假设我们要对 U(0,1) 的偶数求和,所以 n=2m。同样,谈论 G(0,1) 作为 N(0,1)

的近似值
G(0,1) = (Sum_1^2m U(0,1) - m ) / sqrt(m/6)

我们改写为

G(0,1) = (Sum_1^m U(0,1) - (m - Sum_1^m U(0,1)))/sqrt(m/6) =
       = (Sum_1^m U(0,1) - Sum_1^m(1 - U(0,1)))/sqrt(m/6)

由于 1 - U(0,1)U(0,1) 具有相同的分布,我们可以 将G(0,1)写成对称形式

G(0,1) = (Sum_1^m U(0,1) - Sum_1^m U(0,1))/sqrt(m/6) =
       = Sum_1^m (U(0,1) - U(0,1)) / sqrt(m/6)

对随机数求和提供了一个最大值是均值两倍的分布,因此严重限制了该方法。似乎无法正确近似正态分布。