根据Why are floating point numbers inaccurate?,浮点数有误。
我的问题是,对于正整数n,Math.random()* n是否有错误,导致其结果等于或大于n?
答案 0 :(得分:5)
Math.random() * n
的结果不会大于或等于n
,因为Math.random()
返回浮点数x
,其中0 <= x < 1
。 Math.random()
函数的文档为here
答案 1 :(得分:4)
如果 n 在浮点格式的正常范围内,则Math.Random()*n
< n 。
随后是一个证明。
code format
编写的表达式是指计算值。代码格式之外的表达式是指精确的数学。对于任何数字 n ,n
是将 n 舍入为浮点格式的结果。 a
•b
是浮点舍入之前a
和b
的精确数学乘积,而a*b
是舍入之后的浮点结果。 / li>
n
是正常的。这意味着2 m •(1−2 − p )≤ n < 2 M +1 •(1-2−sup> − p ),其中 m 和 M 是浮点格式的最小和最大指数(对于IEEE-754 64位二进制浮点,−1022和1023)。给出 a < b ,考虑将它们四舍五入为浮点格式a
和b
的结果(使用四舍五入-最紧密的关系到均匀的规则)。
假设b
<a
。
如果a
≤ a ,则b
<a
≤ a < b 。这是不可能的,因为b
离 b 比a
更远,因此 b 必须四舍五入到a
或更接近的数字,而不是b
。相反,如果 a <a
,则 a ≤b
<a
或b
< a <a
。在前一种情况下,由于a
更近, a 不能四舍五入到b
。在后一种情况下,如果a
≤ b ,则由于b
更近,因此 b 不能四舍五入到a
,并且,如果 b <a
,则由于a
更近, a 无法舍入到b
。
因此不可能是b
<a
;必须是a
≤b
。
乘以正数 y 是弱单调的,因为如果
x 0 < x 1 ,然后是 x 0 •y < x 1 •y,
引理0告诉我们x0*y
≤x1*y
。
让 g 成为Math.Random()
的最大可能结果。由于JavaScript的Math.Random()
返回[0,1)中的数字,因此 g 为1-2 - p 。
根据引理1,如果g*n
< n ,则Math.random()
的任何结果 x ≤ g 都满足{ {1}} < n 。
我们将证明x*n
<g*n
,然后证明这意味着n
< n 。
考虑g*n
。如果g*n
正好是2的幂,则n
•g
可以浮点格式精确表示,并且没有舍入,因此n
=(1 −2 − p )•g*n
<n
。如果n
不是2的幂,则n
•g
是(1-2−sup>- p )•{{ 1}} = n
-n
•2 - p 。后者比n
小n
的½ULP以上,因此,当将其四舍五入为浮点格式时,会将其四舍五入,从而产生小于{{1} }。 (请注意,对于任何数字 n 而言,这是不正确的,因为n
可能处于非正常范围内,其中ULP可能大于n
•2 1− p 。但是,我们假设 n 在正常范围内,对于所有正整数,直到n
溢出。)
因此g*n
<n
。最后,我们考虑以下可能性:当 n 舍入为浮点格式时,结果n
大于 n ,这可能导致g*n
> n 。但是,n
<n
要求g*n
比g*n
小至少1个ULP,但将 n 舍入到n
最多可以将值增加1/2 ULP。所以g*n
< n 。
答案 2 :(得分:2)
答案是肯定的,但仅在非常极端的情况下。
有可能
Math.random()*n >= n
在n很大的情况下返回true。
请注意,在这些情况下,结果将等于所选数字n。
来自Math.random()
documentation:
请注意,由于JavaScript中的数字是IEEE 754浮点数,具有从近似到最接近的行为,因此以下函数所声明的范围(不包括Math.random()本身的范围)不准确。如果选择了很大的界限(253或更高),则在极少数情况下可以计算通常不包括的上限。
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
尽管从技术上讲是可能的,但这种情况非常罕见,可以忽略不计
答案 3 :(得分:0)
我只想添加一些可能有用的信息,实际上,如果n
设置为Number.POSITIVE_INFINITY,则条件变为true
:
let posInf = Number.POSITIVE_INFINITY;
console.log(Math.random(), posInf);
console.log(Math.random() * posInf >= posInf);