奇怪的JavaScript编号行为

Ash*_*bhu 6 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
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?我知道JavaScript只能代表数字2^53(它们内部是'双'?),但为什么会出现这种情况呢?

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

Cra*_*sta 10

这个数字确实是一个双倍.尾数有52位(关于双精度的源和额外信息).因此,从一位存储2 ^ 53个剁.

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

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

我可能会有一些细节,但基本的想法就在那里.因此当数字是2 ^ 53,2 ^(E-1023)= 2 ^ 53并且因为M中只有52位,所以你不能再代表最低位.


Nic*_*ole 5

@CrazyCasta给出的答案很好.

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

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

正如您所演示的那样,它可以存储大于2^53,但精度更差的数字2^0.随着数字越来越大,它们失去了越来越多的精确度.

因此,最大值Number.MAX_VALUE意味着它可以代表的"最大"值; 但这并不意味着准确度与接近2^1或的值相同2^53.

对此的推论是Number可以包含Number.MIN_VALUE最小值 ; 不是最消极的.也就是说,它是最接近零的非零数字:( 5.00E-324注意这是一个正数!).

  • 这是一个类比:你在纽约市中心,你被告知到伦敦市中心的距离是3465英里.现在你向西方迈出了一步.离伦敦还有3465英里.该测量的精度以英里为单位,因此添加几英寸或英尺不会改变它. (2认同)