奇怪的JavaScript编号行为

时间:2012-09-26 05:44:18

标签: javascript numbers

我在处理JavaScript数字时发现了以下奇怪的行为。

var baseNum = Math.pow(2, 53);
console.log(baseNum); //prints 9007199254740992

console.log(baseNum + 1); //prints 9007199254740992 again!

console.log(baseNum + 2); //prints 9007199254740994, 2 more than +1

console.log(baseNum + 3) // prints 9007199254740996, 2 more than +2
console.log(baseNum + 4) // prints 9007199254740996, same as +3

这里发生了什么?我理解JavaScript只能表示高达2^53的数字(它们在内部是“双重”?),但为什么会出现这种情况呢?

如果2^53是实际最大值,那么为什么我们有Number.MAX_VALUE1.7976931348623157e+308)?

3 个答案:

答案 0 :(得分:10)

这个数字确实是一个双倍。尾数有52位(source and extra information on doubles)。因此,从一位存储2 ^ 53个印章。

使用3个符号位(相当直接)和另外两个部分(尾数M和指数E)存储该数字。该数字计算如下:

(1 + M / 2 ^ 53)* 2 ^(E-1023)

我可能会有一些细节,但基本的想法是存在的。因此,当数字为2 ^ 53时,2 ^(E-1023)= 2 ^ 53且由于M中只有52位,因此您不能再代表最低位。

答案 1 :(得分:5)

@CrazyCasta给出的答案很好。

唯一要补充的是你的第二个问题:

  

如果2^53是实际最大值,那么为什么我们有Number.MAX_VALUE1.7976931348623157e+308)?

如您所示,可以存储大于2^53的数字,但精度低于2^0。随着数字越来越大,它们失去了越来越多的精确度。

因此Number.MAX_VALUE中的最大值表示它可以表示的“最大”值;但这并不意味着准确度与2^12^53附近的值相同。

这是一个必然结果,Number.MIN_VALUE是Number可以包含的最小值;不是最负面的。也就是说,它是最接近零的非零数字:5.00E-324(注意这是一个正数!)。

答案 2 :(得分:2)

long中可存储的最大值远远大于可存储的的精确度的最大值。浮点数具有固定的最大有效位数,但数字的大小可以变得更大。

为指数分配了一定数量的比特(2的幂),并且隐含地乘以存储在其余比特中的尾数。超过某一点,你会失去精确度,但你可以继续增加指数来表示更大和更大的数量。