【问题标题】:Bias in randomizing normally distributed numbers (javascript)随机化正态分布数字的偏差(javascript)
【发布时间】:2013-02-23 03:04:50
【问题描述】:

我在生成正态分布随机数时遇到问题 (mu=0 sigma=1) 使用 JavaScript。

我已经尝试过 Box-Muller 的方法和 ziggurat,但生成的一系列数字的平均值为 0.0015 或 -0.0018 - 与零相差甚远!超过 500,000 个随机生成的数字,这是一个大问题。它应该接近于零,例如 0.000000000001。

我不知道是方法问题,还是 JavaScript 的内置 Math.random() 生成的数字不完全均匀分布。

有没有人发现类似的问题?

您可以在这里找到 ziggurat 功能:

http://www.filosophy.org/post/35/normaldistributed_random_values_in_javascript_using_the_ziggurat_algorithm/

下面是 Box-Muller 的代码:

function rnd_bmt() {
    var x = 0, y = 0, rds, c;

    // Get two random numbers from -1 to 1.
    // If the radius is zero or greater than 1, throw them out and pick two
    // new ones. Rejection sampling throws away about 20% of the pairs.
    do {
        x = Math.random()*2-1;
        y = Math.random()*2-1;
        rds = x*x + y*y;
    }
    while (rds === 0 || rds > 1) 

    // This magic is the Box-Muller Transform
    c = Math.sqrt(-2*Math.log(rds)/rds);

    // It always creates a pair of numbers. I'll return them in an array. 
    // This function is quite efficient so don't be afraid to throw one away
    // if you don't need both.
    return [x*c, y*c];
}

【问题讨论】:

  • 如果您发布代码会更容易帮助您。

标签: javascript random numbers generator


【解决方案1】:

如果您生成n 独立正态随机变量,则standard deviation of the mean 将是sigma / sqrt(n)

在您的情况下 n = 500000sigma = 1 因此均值的标准误差约为 1 / 707 = 0.0014。给定 0 均值的 95% 置信区间大约是这个值的两倍或(-0.0028, 0.0028)。您的样本均值正好在此范围内。

您对获得0.000000000001 (1e-12) 的期望没有数学基础。为了达到这个准确度范围,您需要生成大约10^24 样本。每秒 10,000 个样本仍然需要 3 万亿年才能完成……这正是为什么尽可能避免通过模拟计算事物的原因。

另一方面,您的算法似乎实现正确:)

【讨论】:

  • 最后一个问题:如果我必须在给定样本均值和方差的情况下生成一个由 500000 个数字组成的对数正态分布序列,我是否必须调整一些参数才能获得与原始样本完全相同的均值?
  • 查看如何计算对数正态给定参数的均值和方差:en.wikipedia.org/wiki/Lognormal_distribution
  • “每秒 10,000 个样本仍需要 3 万亿年才能完成”——我使用 Redis 完成,在我的 MacBook Pro 上花了 6 分钟。
  • 你生成了 10^24 个正态随机变量?我想你指的是 500,000;再加上 Redis 会比 Javascript 快很多。