对于正整数n,Math.random()* n> = n是否可能?

时间:2019-02-19 03:39:39

标签: javascript floating-point

根据Why are floating point numbers inaccurate?,浮点数有误。

我的问题是,对于正整数n,Math.random()* n是否有错误,导致其结果等于或大于n?

4 个答案:

答案 0 :(得分:5)

Math.random() * n的结果不会大于或等于n,因为Math.random()返回浮点数x,其中0 <= x < 1Math.random()函数的文档为here

答案 1 :(得分:4)

如果 n 在浮点格式的正常范围内,则Math.Random()*n < n

随后是一个证明。

初步

  • 在此答案中,用code format编写的表达式是指计算值。代码格式之外的表达式是指精确的数学。对于任何数字 n n是将 n 舍入为浮点格式的结果。 ab是浮点舍入之前ab的精确数学乘积,而a*b是舍入之后的浮点结果。 / li>
  • 使用IEEE-754二进制浮点,舍入到最近的关系到偶数。需要对IEEE-754有一定的了解。
  • ULP代表最低精度单位。它是特定数字浮点表示形式的有效位的最低有效位的值。
  • p 是浮点表示形式的有效位数。对于IEEE-754基本的64位二进制浮点, p 为53,但这证明适用于其他宽度。
  • 如果 h 是正常浮点表示形式中有效位数的高位表示的值(由于按指数进行缩放),则 h •2 < sup> 1− p 是低位表示的值,并且是表示数字的ULP, h •2 - p 是½ULP,它是通过将此指数范围内的任何数字四舍五入为浮点格式而可以产生的最大变化。
  • 通过“ n 在正常范围内”,我的意思是n是正常的。这意味着2 m •(1−2 p )≤ n < 2 M +1 •(1-2−sup> − p ),其中 m M 是浮点格式的最小和最大指数(对于IEEE-754 64位二进制浮点,−1022和1023)。

引理0:舍入微弱单调

给出 a < b ,考虑将它们四舍五入为浮点格式ab的结果(使用四舍五入-最紧密的关系到均匀的规则)。

假设b <a

如果a a ,则b <a a < b 。这是不可能的,因为b b a更远,因此 b 必须四舍五入到a或更接近的数字,而不是b。相反,如果 a <a,则 a b <ab < a <a。在前一种情况下,由于a更近, a 不能四舍五入到b。在后一种情况下,如果a b ,则由于b更近,因此 b 不能四舍五入到a,并且,如果 b <a,则由于a更近, a 无法舍入到b

因此不可能是b <a;必须是ab

引理1:浮点乘法是弱单调的

乘以正数 y 是弱单调的,因为如果 x 0 < x 1 ,然后是 x 0 •y < x 1 •y, 引理0告诉我们x0*yx1*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的幂,则ng可以浮点格式精确表示,并且没有舍入,因此n =(1 −2 p )•g*n <n。如果n不是2的幂,则ng是(1-2−sup>- p )•{{ 1}} = n-n•2 - p 。后者比nn的½ULP以上,因此,当将其四舍五入为浮点格式时,会将其四舍五入,从而产生小于{{1} }。 (请注意,对于任何数字 n 而言,这是不正确的,因为n可能处于非正常范围内,其中ULP可能大于n •2 1− p 。但是,我们假设 n 在正常范围内,对于所有正整数,直到n溢出。)

因此g*n <n。最后,我们考虑以下可能性:当 n 舍入为浮点格式时,结果n大于 n ,这可能导致g*n> n 。但是,n <n要求g*ng*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);