Javascript 使用Math.random()获得通常排除的上界的几率

Javascript 使用Math.random()获得通常排除的上界的几率,javascript,Javascript,这看起来更像是一个数学问题,但由于它专门链接到Javascript的伪随机数生成器,我想它很适合这样做。如果没有,请随意将其移到其他地方 首先,我知道ES没有指定伪随机数生成器中要使用的算法-Math.random()-,但它确实指定范围应具有近似的均匀分布: 使用依赖于实现的算法或策略,返回带正号、大于或等于0但小于1、随机或伪随机选择、在该范围内近似均匀分布的数值。此函数不接受任何参数 到目前为止,一切顺利。我最近偶然发现了以下数据: 请注意,由于JavaScript中的数字是IEEE 75

这看起来更像是一个数学问题,但由于它专门链接到Javascript的伪随机数生成器,我想它很适合这样做。如果没有,请随意将其移到其他地方

首先,我知道ES没有指定伪随机数生成器中要使用的算法-
Math.random()
-,但它确实指定范围应具有近似的均匀分布:

使用依赖于实现的算法或策略,返回带正号、大于或等于0但小于1、随机或伪随机选择、在该范围内近似均匀分布的数值。此函数不接受任何参数

到目前为止,一切顺利。我最近偶然发现了以下数据:

请注意,由于JavaScript中的数字是IEEE 754浮点数字,具有从四舍五入到最近的偶数的行为,因此这些范围(不包括
Math.random()
本身的范围)并不精确,并且取决于界限,在极少数情况下可能出现这种情况(在2^62中的1的顺序)计算通常排除的上限

好的。这让我进行了一些测试,结果(显然)在Chrome控制台和Firefox的Firebug上是相同的:

>> 0.99999999999999995
1
>> 0.999999999999999945
1
>> 0.999999999999999944
0.9999999999999999
让我们用一个简单的实际例子来说明我的问题:

Math.floor(Math.random() * 1)
考虑到上面的代码,IEEE 754浮点数具有四舍五入到最近的偶数行为,在对
Math.random()
范围进行均匀分布的评估后,我得出结论,它返回通常排除的上限(
1
在我上面的代码中)的几率为
0.0000000000000000 5555555…
,这大约是
1/18000000000000000

现在查看MDN编号,
1/2^62
计算结果为
1/4611686018427387904
,即比我的计算结果小200多倍

我算错了吗?Firefox的伪随机数生成器是否分布不均匀,无法产生200倍的差异


我知道如何解决这个问题,而且我知道这样的小概率甚至不应该被考虑用于每天的使用,但我很想了解这里发生了什么,如果我的数学坏了或是Mozilla的(我希望它是以前的)
=]
欢迎您的任何输入。

您不必担心将Math.random()中的数字舍入为1

当我在查看IE、Chrome和FF当前版本中的实现(根据我得到的结果推断)时,有几个观察结果几乎可以肯定地表明,您应该始终以二进制形式获得0到0.11111111111111111111111111之间的数字(这是
0.99999999999944.toString(2)
和一些较小的十进制数)


Chrome:这里很简单。它通过生成32位数字并将其除以1来生成数字,我记得所有
数学实现的分布情况。random
一点也不均匀,可以通过直接从wikipedia实现的函数来击败。谢谢,您总是提供非常有用的ES/JS related关于我的问题的数据@Esailija
=]
这可能有点不对劲,但是,
Math.pow(2,62)。toString(2)
返回63位,但是JS会在第54位的正位上取整到上限。不确定这个计算是否正确。我想我需要深入研究。
.toString(2)
与数字位无关,它是二进制数字系统转换。因此,它甚至可以与
Math.pow(21000).toString(2)
等等一起工作,
toString(2)
与JS浮点后面的实际二进制文件完全无关。
Math.pow(21000).toString(2).length
1001
…但是double下的实际位数总是64。
+1
非常有用的数据,谢谢。对于这个问题,我主要关注Firefox实现,因为数据来自MDN和其他JS实现(包括封闭源代码实现)将有所不同。尽管拥有其他实现的数据很好。
=]
但是,在调用
之前,只有一件事。
Math.random()
的结果可能已经经历了舍入,以适应JS的53位尾数,不是吗?同时查看:“For
Math.random()
,MS IE 8将“1”位显示为第53位,对于第54位,设置位1时除外(随机值≥ 0.5)。Firefox和Opera很好,从“1”位到第53位。Safari和Chrome显示从“1”位到第32位。(2010-12-09,当前浏览器版本。)“到目前为止,一切都与您的答案相匹配。正是因为这个原因,尾数只是一个已知位数的序列,随机数生成器只会变得更糟(就效率和舍入问题而言)如果它没有这样对待它。顺便说一句,在您的示例中,大多数舍入都是另一种类型-在解析十进制表示时舍入。您可以看到0.9999999999944==0.9999999999999834。是的,正如
0.9999999999999999944
计算结果为
0.99999999999999999
0.99999999999999999834
一样。只有在我将您的答案标记为已接受之前,还有一个问题,如果您查看该问题的注释,
.toString(2)
您使用的方法似乎与数字位/尾数无关。但它与您的结果和我上面链接的页面结果的匹配方式很奇怪。我缺少的二进制表示法和尾数之间是否存在任何关系?十进制表示法的问题是,它不能很好地映射到m、 。因此,0.9999999999999944的计算结果并不是0.99999999999999,而是一个满1的尾数,这不是同一个数字。一个很好的例子是.2.toString(2),它表明0.2只是t中的近似值