最大安全整数是否可以用IEEE双格式2^53或2^54表示



我在多篇文章中看到,IEEE双格式中可表示的最大安全整数是2^53:https://stackoverflow.com/a/3793950

https://stackoverflow.com/a/1848768

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

但有一篇帖子说它是2^54:https://stackoverflow.com/a/12445693

可以表示所有整数的范围(包括边界)2^54作为上限-2^54作为下限

这个答案是错的还是我遗漏了什么?

编辑:

上面的帖子现在似乎被更正了。

但有一篇帖子说它是2^54:https://stackoverflow.com/a/12445693

所有整数都可以表示的范围(包括边界)2^54作为上界-2^54作为下界

这个答案是错的还是我遗漏了什么?

你没有遗漏什么。IEEE 754双精度二进制浮点("double")不能表示的第一个整数是2^53+1,这完全在所要求的-2^54..2^54的范围内。这可能是一个拼写错误,因为范围为-2^53..2^53(包括在内)的所有整数都可以表示。从2^53开始,只能表示2的倍数(所以2^53+2可以,但2^53+1不行)。由于JavaScript使用这种形式的double,因此很容易在实际操作中看到:

const x = 2**53;
const y = x + 1;
console.log(x.toLocaleString()); // 9,007,199,254,740,992
console.log(y.toLocaleString()); // 9,007,199,254,740,992 -- the same
console.log(x === y);            // true
const z = x + 2;
console.log(z.toLocaleString()); // 9,007,199,254,740,994

对于双精度,2^53-1是最后一个所谓的";"安全";整数,其中";"安全";定义为";你可以加1得到下一个整数"(事实上,JavaScript甚至有一个值为2^53-1:Number.MAX_SAFE_INTEGER的常数。)当你加1时,你得到的下一个整数是(当然)2^53——格式无法再处理每个不同整数的第一个整数。从2^53开始,double只能计数2:2^53,2^53+2,2^53/4。。。也就是说,在这一点上,它只能存储2的倍数。(后来,它只能按4的倍数计数,后来只能按8的倍数计数。)

为了完整性:该格式可以(准确地)表示许多更大的整数,只是在这个幅度上,它不能表示所有的整数,因为该格式使用基值(尾数)和指数,当你达到2^53时,指数只能表示偶数(2的倍数)。稍后,指数再次滚动,只能表示4的倍数,等等。

让我们把它想象一下。IEEE-754相当复杂,但让我们举一个简化的例子(不是IEEE-754)来解释。假设我们有四位来存储指数,八位来存储尾数,假设我们只存储整数。这意味着当指数=1时,我们可以存储0到255的值:

概念,*NOT*IEEE-754!指数(二进制)Mantissa(二进制)结果值(十进制)0 0 0 1 0 0 0 00 0 1 0 0 0 0 1 10 0 1 0 0 0 0 1 2。。。0 0 1 1 1 1 11 1 1 1 0 2540 0 0 1 1 1 1 11 1 1 1 255

我们的尾数已达到最大值,因此我们通过使用指数=2并使尾数为2的倍数来牺牲范围的精度。现在我们只能按2计数:

概念,*NOT*IEEE-754!指数(二进制)Mantissa(二进制)结果值(十进制)0 0 2 0 0 0 0 1 20 0 2 0 0 0 0 1 0 4。。。0 0 0 2 0 1 1 1 1 11 1 2540 0 2 1 0 0 0 00 0 2 1 0 0 0 0 1 258。。。0 0 2 1 1 1 1 11 1 1 0 5080 0 0 2 1 1 1 1 11 1 1 1 510

请注意,我们可以精确地表示值256,即使它超出了尾数本身可以处理的范围(0-255),因为对于指数,我们取尾数值(128)并将其加倍以得到256。这正是双冠王2^53的表现。但我们不能表示257,因为在这个量级上,我们只能处理2的倍数。这就是双精度中2^53+1的情况,我们不能表示它。不过我们可以表示2^53+2。

IEEE-754双精度格式中可表示的最大安全整数为2^53-1。如果您尝试存储大于此值的值,它将不再安全。虽然可以存储较大的整数,但如果你想确保它保持安全,我建议不要这样做,因为它们在2^53-1以上会变得不精确。编辑:正如Eric的评论所解释的那样,这些值本身仍然是精确的,但当进行算术时,它们就是四舍五入的。

最新更新