JavaScript如何处理大整数(超过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如何处理大整数?

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.MIN_SAFE_INTEGER的值为 −9007199254740991 (−(253−1))。

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

Number.MAX_SAFE_INTEGER的值是最大的整数 n 这样的 n 和 n + 1 都可以完全表示为数字值。

Number.MAX_SAFE_INTEGER的价值是9007199254740991 (253−1)。

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

console.log( Number.MAX_SAFE_INTEGER );

其余的都是用 MDN 编写的:

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

在此上下文中,安全是指表示整数的能力 确切地并正确比较它们。例如 Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2意志 求值为 true ,这在数学上是不正确的。看 Number.isSafeInteger()了解更多信息。

.:: 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 库对字符串中的大整数进行编码,并对它们执行算术运算。

这是全文。

Number.MAX_VALUE将告诉您JS实现中可表示的最大浮点值。答案可能是:1.7976931348623157e+308。但这并不意味着每个最多 10^308 的整数都可以精确地表示。如示例代码所示,超过 2^53 只能表示偶数,并且随着您在数字线上走得更远,差距会变大。

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

李蒙的比格特

紧缩

为了补充这里的其他答案,值得一提的是 BigInt 的存在。 这允许 JavaScript 处理任意大的整数。

在号码上使用n后缀,并使用常规运算符,如 2n ** 53n + 2n 。 需要指出的是,BigInt 不是数字,但您可以通过显式转换与 Number 进行范围有限的互操作。

Node.js REPL中的一些示例:

> 9999999999999999999999999999999n + 1n10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000> 2n ** 53n9007199254740992n> 2n ** 53n + 1n9007199254740993n> 2n ** 53n == 2n ** 53n + 1n假>类型1n"比金特"> 3 * 4n类型错误:不能混合使用 BigInt 和其他类型,请使用显式转换> 大国际(3) * 4n32,> 3 * 数字(4n)12> 数字(2n ** 53n) == 数字(2n ** 53n + 1n)真

相关内容

  • 没有找到相关文章

最新更新