【问题标题】:Why does this random() distribution look asymmetric?为什么这个 random() 分布看起来不对称?
【发布时间】:2014-10-06 00:34:43
【问题描述】:

编辑:这是使用 Google Chrome 36

我在搞乱 html5 画布,生成随机分布在立方体内的点并将其投影到 2D 画布上。令人惊讶的是,结果看起来一点也不对称,我怀疑 Javascript 的 Math.random() 让我失望了。

谁能告诉我为什么会这样?有没有可能让它看起来真的很随机​​,而不让它变慢?

var ctx = canvas.getContext('2d');

for (var i = 0; i < 10000000; i++) {
    var x = Math.random()*2-1, y = Math.random()*2-1, z = 2+Math.random()*2-1;
    x = (.5 + .5*x/z) * canvas.width;
    y = (.5 + .5*y/z) * canvas.height;
    ctx.fillRect(Math.floor(x), Math.floor(y), 1, 1);
}

http://jsfiddle.net/y10tvj26/(加载需要一段时间)

【问题讨论】:

  • 您是想在边缘聚集,还是希望它在整个正方形中真正随机?
  • 你用的是什么浏览器?在 Opera 中完全没问题。
  • 在 Firefox 中看起来也不错,那些白线不存在。
  • @Bergi 我在 Chrome 38.0.2121.3 中看到了描述的行为。

标签: javascript google-chrome canvas random prng


【解决方案1】:

Chrome 有一个documented issue,随后对 Math.random() 的调用是相关的。在您的算法中,相关值往往会落在画布上的一条线上。对 Math.random() 的额外调用打破了这种相关性。我还没有看到其他浏览器受到影响的报告。

只需在每次通话中多拨一次Math.random(),您就会得到您想要的。

var ctx = canvas.getContext('2d');

function r() {
    Math.random();
    return Math.random();
}
for (var i=0; i<10000000; i++) {
    var x = r()*2-1, y = r()*2-1, z = 2+r()*2-1;
    x = (.5 + .5*(x/z)) * canvas.width;
    y = (.5 + .5*(y/z)) * canvas.height;
    ctx.fillRect(x, y, 1, 1);
}

更新于:http://jsfiddle.net/y10tvj26/5/

【讨论】:

  • 为什么?请解释这是如何解决问题的。此外,OP 确实询问了为什么模式首先出现的原因,而不是[仅]如何处理它。
  • 我在另一个答案下方对此发表了评论,否则会产生误导。我编辑了我的回复以包括原因和参考。
  • 谢谢,这听起来是个可行的理由 :-)
【解决方案2】:

这是一个伪随机数生成与随机生成的例子。基本上,当您生成伪随机数(例如使用 Math.random() 函数)时,有些数字会比其他数字更频繁地出现。有关差异的更多信息,请参阅here

就实际上使它看起来更“随机”而言,我会注意到,对于较小的 i 范围,图像看起来确实是随机的,只有当您选择一个非常大的值时,缺陷才会变得明显。此外,我也不认为为 Math.random 设置自己的种子是一个适当的解决方案,因为当您进行大量迭代时,您仍然会看到“随机性”的退化。

一个潜在的解决方案是使用不同的库来生成伪随机数,看看它是否会产生更好看的输出。除此之外,你几乎受限于计算机的确定性属性(至少在强大的量子计算机出现在市场上之前!)。

编辑 - 此问题是 Google Chrome 的 Math.random() 实现所独有的,并记录在以下位置: Why is Google Chrome's Math.random number generator not *that* random? https://code.google.com/p/chromium/issues/detail?id=276886 https://code.google.com/p/v8/issues/detail?id=558

【讨论】:

  • 出现频率高于其他数字的数字?不,为此需要对实施进行严格的改进。以模式出现的数字(例如在绘画图像时变得可见),是的,当使用糟糕的算法时可能会发生这种情况。
  • @Bergi 因为此错误仅在 Chrome 中报告,但似乎虽然是随机的(请参阅 xkcd.com/221),但随机数生成器出现了一些问题。有些数字确实比其他数字更有可能。
  • 查看代码,问题在于对 Math.random() 的相邻调用之间的相关性。您可以玩游戏过滤生成器中的特定位,但问题仍然存在。每次额外的调用似乎都有效。
  • @Erik:您链接的两个错误报告都讨论了 V8 的 random() 函数的低。但是,您的第一段表明 distribution 将是不均匀的 - 事实并非如此。
  • 如文档中所述“随机数生成器是从当前时间播种的”,所以也许是调用之间的额外时间有所不同?此外,这并没有解释为什么代码只在 Chrome 中失败,突出了它如何生成随机数的问题。
猜你喜欢
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 2020-02-21
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
相关资源
最近更新 更多