分配 BigInt 存储错误的数字(数字 + 1)

Assigning BigInt stores wrong number (number+1)

我想在JavaScript中定义一个BigInt号码。但是当我分配它时,存储了错误的号码。实际上在存储的时候数字加了1。

let num = BigInt(0b0000111111111111111111111111111111111111111111111111111111111111)
console.log(num)                // Output: 1152921504606846976n
console.log(num.toString(2))    // Output: 1000000000000000000000000000000000000000000000000000000000000

所以存储的数字是1152921504606846976,但应该是11529215046068469765。这是为什么?

将数字转换为 BigInt 无法创建以前不存在的位。
0b1(就像 1)是一个数字文字,所以它创建了一个数字。
0b1n(就像 1n)是一个 BigInt 文字,所以它创建了一个 BigInt。

通过编写 BigInt(0b1),您首先创建一个 Number,然后将其转换为 BigInt。只要值为 1,就可以正常工作;一旦该值超过您可以无损存储在 Number [1] 中的值,您将看到最终 BigInt 的值将与您写下的文字不匹配。无论您使用二进制 (0b...)、十进制还是十六进制 (0x...) 文字都不会改变任何一个。
(而且要特别清楚:没有理由写 BigInt(123n),就像你不会写 Number(123) 一样。123n 已经是一个 BigInt,所以没有什么可以转换的。)

一个简单的 non-BigInt 说明发生了什么的方法是在您最喜欢的浏览器的 DevTools 控制台中输入 12345678901234567890:您可以指定任意长度的数字文字,但它们将被解析为IEEE754 64 位“double”,精度有限。文字中的任何额外数字都无法存储,当然每个数字的存在都会影响数字的大小。

[1] 旁注:这个条件比仅仅说 Number.MAX_SAFE_INTEGER 是阈值更微妙,尽管该常数与情况有关:可以存储低于 MAX_SAFE_INTEGER 的任何整数无损,但 MAX_SAFE_INTEGER 以上的许多数字也可以精确表示。随机示例:1e20.