如何处理大整数(超过52位)?

考虑这个代码(节点v5.0.0)

const a = Math.pow(2, 53) const b = Math.pow(2, 53) + 1 const c = Math.pow(2, 53) + 2 console.log(a === b) // true console.log(a === c) // false 

为什么a === b是真的?

什么是javascript可以处理的最大整数值?

我正在实现随机整数发生器高达2 ^ 64。 我应该知道有什么陷阱吗?

。:: JavaScript只支持53位整数::。

JavaScript中的所有数字都是浮点数,这意味着整数始终表示为

 sign × mantissa × 2exponent 

尾数有53位。 你可以使用指数来获得更高的整数,但是它们将不再是连续的。 例如,您通常需要将尾数乘以2(指数1)才能达到第54位。

但是,如果乘以2,则只能表示每个第二个整数:

 Math.pow(2, 53) // 54 bits 9007199254740992 Math.pow(2, 53) + 1 // 9007199254740992 Math.pow(2, 53) + 2 //9007199254740994 Math.pow(2, 53) + 3 //9007199254740996 Math.pow(2, 53) + 4 //9007199254740996 

添加期间的舍入效果会使奇数增量变得不可预测(+1对+3)。 实际的表示有点复杂,但这个解释应该可以帮助你理解基本问题。

您可以安全地使用strint库来对string中的大整数进行编码,并对它们进行算术运算。

这是完整的文章。

回答你的第二个问题,这里是你在JavaScript中的最大安全整数

 console.log( Number.MAX_SAFE_INTEGER ); 

其余的都是用MDN编写的:

MAX_SAFE_INTEGER常量的值为9007199254740991 。 这个数字背后的原因是,JavaScript使用IEEE 754中规定的双精度浮点格式数字,只能安全地表示-(253 - 1)253 - 1之间的数字。

在这种情况下,安全是指能够精确表示整数并正确比较它们。 例如, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2将计算为true ,这在math上是不正确的。 有关更多信息,请参阅Number.isSafeInteger()

JavaScript如何处理大整数?

JS没有整数。 JS号码是64位浮点数。 它们被存储为尾数和指数。

精度由尾数给出,幅度由指数给出。

如果你的数字需要比尾数存储更多的精度,最不重要的位将被截断。

 9007199254740992; // 9007199254740992 (9007199254740992).toString(2); // "100000000000000000000000000000000000000000000000000000" // \ \ ... /\ // 1 10 53 54 // The 54-th is not stored, but is not a problem because it's 0 9007199254740993; // 9007199254740992 (9007199254740993).toString(2); // "100000000000000000000000000000000000000000000000000000" // \ \ ... /\ // 1 10 53 54 // The 54-th bit should be 1, but the mantissa only has 53 bits! 9007199254740994; // 9007199254740994 (9007199254740994).toString(2); // "100000000000000000000000000000000000000000000000000010" // \ \ ... /\ // 1 10 53 54 // The 54-th is not stored, but is not a problem because it's 0 

那么,你可以存储所有这些整数:

 -9007199254740992, -9007199254740991, ..., 9007199254740991, 9007199254740992 

第二个被称为最小安全整数 :

Number.MIN_SAFE_INTEGER的值是最小的整数n,这样n和n-1都可以精确地表示为一个Number值。

Number.MIN_SAFE_INTEGER的值是-9007199254740991( – (2 53 -1))。

倒数第二个被称为最大安全整数 :

Number.MAX_SAFE_INTEGER的值是最大的整数n,使得n和n + 1都可以精确地表示为Number值。

Number.MAX_SAFE_INTEGER的值是9007199254740991(2 53 -1)。

Number.MAX_VALUE会告诉你在你的JS实现中表示的最大的浮点值。 答案可能是:1.7976931348623157e + 308。 但这并不意味着每个10 ^ 308以下的整数都可以精确地表示出来。 正如你的例子所显示的,除了2 ^ 53之外,只有偶数可以表示出来,而当你走出数字线时,差距会变得更大。

如果你需要大于2 ^ 53的精确整数,你可能需要使用一个bignum包,它允许任意大的整数(在可用内存的范围内)。 我碰巧知道的两个包是:

BigInt由Leemon

紧缩