Math.random和JavaScript Web编程

8
根据这个Stack Overflow帖子,JavaScript中的Math.random()取决于浏览器或操作系统。基本上,这意味着JavaScript没有生成均匀随机变量的标准算法。这个帖子似乎表明Chrome的均匀随机数算法特别糟糕。
在我的程序中,我尝试根据一些信息和随机噪声来理解用户的行为。我使用Box-Muller变换对由Math.random()生成的数字进行处理,以生成高斯随机数。这是否意味着使用不同浏览器的用户将经历不同类型的噪声?请注意,我使用Box Muller是因为我不关心速度,但我知道它可能会对伪随机数的生成方式特别敏感。似乎有很多关于为什么Math.random()不好的帖子,但是关于实际使用什么替代方法的帖子并不多。什么是最佳实践?因为我使用Box-Muller转换为高斯数,所以有什么需要特别注意的吗?

你可能对JavaScript感兴趣 - 为什么提到了Java并打了标签呢? - Michael Petrotta
15
Java和JavaScript之间的关系就像车和地毯一样,二者并无太大关联。 - Iłya Bursov
1
sorry for the typo, fixed - WetlabStudent
6
考虑使用AJAX请求在线随机数生成API以一次获取一批随机数并使用。这意味着无论使用哪个浏览器,这些数字的随机性都来自同一来源。 - struthersneil
2
http://www.random.org/clients/http/ - struthersneil
显示剩余2条评论
2个回答

2
http://en.wikipedia.org/wiki/Xorshift上有一个基于xor-shift的RNG,具有良好的随机性质,应该很容易移植到JavaScript: 编辑已完成:
(function () {
    var x = 123456789;
    var y = 362436069;
    var z = 521288629;
    var w = 88675123;
    var f = Math.pow(2, -32);

    Object.defineProperty(Math, 'xor128', {
        value: function () {
            var t = x ^ (x << 11);
            x = y;
            y = z;
            z = w;
            w = w ^ (w >>> 19) ^ (t ^ (t >>> 8));

            return (w >>> 0) * f;  // convert to floating point          
        }
    });

})();

NB: 这只使用了128位中的32位来生成浮点数结果。理论上,您可以从其他状态变量中组合另外20位以产生52位的结果。

我能看到的最大问题是它不支持种子 - 它将始终生成相同的序列。


有趣的是,我甚至不知道这个算法,不幸的是,缺乏种子集有点成为了致命伤(我不想每次都得到相同的序列)。不过,它可能可以被修改以包括一个种子集,对吧? - WetlabStudent
1
@user1544793 自从发布这个帖子以来,我进行了一些搜索,似乎x、y、z和w中的初始值并不太重要——真正起作用的是位移序列。 - Alnitak

1
一个 Box-Muller 转换仅适用于 均匀分布 的输入。根据 MDN (最后一个例子),Math.random() 不会生成均匀分布的数字。 ECMAScript specification 中关于 Math.random() 的说明如下:

返回一个带有正号的 Number 值,大于或等于 0 但小于 1,在该范围内随机或伪随机选择,使用实现相关的算法或策略,具有近似地在该范围内均匀分布。此函数不带参数。

因此,这取决于浏览器。浏览器可能会但不一定实现完美均匀分布的随机数生成器。
因此,您不能可靠地在Javascript中使用Math.random()在浏览器端实现跨浏览器的Box-Muller转换。

哇,谢谢你。我甚至从来没有想过浏览器部署的算法不一定要使用均匀分布。感谢提供信息! - WetlabStudent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接