这可能看起来更像是一个数学问题,但由于它专门链接到 Javascript 的伪随机数生成器,我想它非常适合 SO。如果没有,请随时将其移至其他地方。
首先,我知道 ES 没有指定要在伪随机数生成器中使用的算法 - Math.random()
-,但它确实指定了范围应该具有近似均匀分布:
15.8.2.14 随机( )
返回一个带正号的数值,大于或等于 0 但小于 1,随机或伪随机选择,在该范围内近似均匀分布,使用与实现相关的算法或策略。此函数不接受任何参数。
到现在为止还挺好。现在我最近偶然发现了来自MDN的这条数据:
请注意,由于 JavaScript 中的数字是具有舍入到最近偶数行为的 IEEE 754 浮点数,因此这些范围(不包括其
Math.random()
本身的范围)并不准确,并且取决于边界,在极少数情况下(在1 in 2^62的顺序)来计算通常排除的上限。
好的。它使我进行了一些测试,结果(显然)在 Chrome 控制台和 Firefox 的 Firebug 上是相同的:
>> 0.99999999999999995
1
>> 0.999999999999999945
1
>> 0.999999999999999944
0.9999999999999999
让我们把它放在一个简单的实际例子中,以使我的问题更清楚:
Math.floor(Math.random() * 1)
考虑到上面的代码,具有舍入到最近偶数行为的 IEEE 754 浮点数,在Math.random()
范围均匀分布的评估下,我得出结论,它返回通常被排除的上限(1
在我上面的代码中)的几率会是0.000000000000000055555...
,也就是大约1/18,000,000,000,000,000
。
现在查看 MDN 编号,1/2^62
计算结果为1/4,611,686,018,427,387,904
,即比我的计算结果小 200 多倍。
我做错数学了吗?Firefox 的伪随机数生成器是否分布不够均匀,无法产生这 200 倍的差异?
我知道如何解决这个问题,而且我知道甚至不应该考虑每天使用这么小的几率,但我很想了解这里发生了什么以及我的数学是否被破坏或 Mozilla 的(我希望它是前者)。=]
任何输入表示赞赏。