JS中的加法如何处理大数

How does addition in JS work with big numbers

在 discord 服务器上练习代码高尔夫时,我们发现一旦数字变大,我们的代码就会停止工作,结果会开始变得混乱。

主要计算是 a=a*10+!(a%2),我们生成的系列中第一个会导致意外结果的 a 是 a=1010101010101010(预期:10101010101010101 vs 实际:10101010101010100).

在调查时我发现计算 10101010101010100 + 1 = 10101010101010100.
看到之后,我尝试了 10101010101010100 + 2 = 10101010101010102 这让我很困惑。为什么加 1 会产生相同的值而加 2 不会?

更多示例:

10101010101010100 + 3 = 10101010101010104
10101010101010102 + 1 = 10101010101010104
10101010101010104 + 1 = 10101010101010104

我也尝试将数字放在 Number() 中以防止任何自动转换(毕竟是 JS),但结果是一样的。

在短暂的延迟后 What is JavaScript's highest integer value that a number can go to without losing precision? 被发布到所说的 discord 中,这似乎解释了为什么结果是这样的,但是 我很好奇控制台表面下发生了什么这会产生这些意想不到的结果。或者在JS中简单定义为未定义的对大数字的算术运算行为?

看到这个documentation

里面提到JavaScript一个数的值是用52位来表示的。随着您的数字越来越接近超过该位数,给定范围内可以表示的数字越来越少。

对于Math.pow(2, 52)Math.pow(2, 53)之间的数字,每个整数都可以表示。即:

Math.pow(2, 52) === Math.pow(2, 52) + 0.5

对于Math.pow(2, 53)Math.pow(2, 54)之间的数字(这是10101010101010100所在的位置),可以表示第二个整数,然后是第四个整数,依此类推,随着范围力量的增长。

console.log('2^52 === 2^52 + 0.5 :', 
  Math.pow(2, 52) === Math.pow(2, 52) + 0.5);
  
console.log('2^53 === 2^53 + 1   :', 
  Math.pow(2, 53) === Math.pow(2, 53) + 1);