为啥 Number.MAX_SAFE_INTEGER 是 9,007,199,254,740,991 而不是 9,007,199,254,740,992?
Posted
技术标签:
【中文标题】为啥 Number.MAX_SAFE_INTEGER 是 9,007,199,254,740,991 而不是 9,007,199,254,740,992?【英文标题】:Why is Number.MAX_SAFE_INTEGER 9,007,199,254,740,991 and not 9,007,199,254,740,992?为什么 Number.MAX_SAFE_INTEGER 是 9,007,199,254,740,991 而不是 9,007,199,254,740,992? 【发布时间】:2014-12-10 09:37:44 【问题描述】:ECMAScript 6 的 Number.MAX_SAFE_INTEGER
应该代表 javascript 在浮点精度问题出现之前可以存储的最大数值。但是,要求添加到此值的数字 1 也必须可以表示为 Number
。
Number.MAX_SAFE_INTEGER
注意
Number.MAX_SAFE_INTEGER
的值是n
的最大整数,因此n
和n + 1
都可以精确地表示为Number
值。
Number.MAX_SAFE_INTEGER
的值为9007199254740991 (2^53−1)
。——ECMAScript Language Specification
Chrome、Firefox、Opera 和 IE11 的 JavaScript 控制台都可以安全地执行数字 9,007,199,254,740,992 的计算。一些测试:
// Valid
Math.pow(2, 53) // 9007199254740992
9007199254740991 + 1 // 9007199254740992
9007199254740992 - 1 // 9007199254740991
9007199254740992 / 2 // 4503599627370496
4503599627370496 * 2 // 9007199254740992
parseInt('20000000000000', 16) // 9007199254740992
parseInt('80000000000', 32) // 9007199254740992
9007199254740992 - 9007199254740992 // 0
9007199254740992 == 9007199254740991 // false
9007199254740992 == 9007199254740992 // true
// Erroneous
9007199254740992 + 1 // 9007199254740992
9007199254740993 + "" // "9007199254740992"
9007199254740992 == 9007199254740993 // true
为什么要求n + 1
也必须可以表示为Number
?为什么失败会使值不安全?
【问题讨论】:
可能是因为2^53 - 1
是最后一个可以准确表示的值 - 2^53
将给出与2^53 + 1
相同的值(“被盗”来自leanpub.com/understandinges6/read#leanpub-auto-numbers)
数字从0
开始..也许是这个原因。
【参考方案1】:
我之所以这么说是因为Math.pow(2, 53)
是最大的可直接表示的整数,但它的 不安全 因为它也是第一个表示的值也是另一个值的近似值:
900719925474099<b><em>2</em></b> == 900719925474099<b><em>3</em></b> // true
对比Math.pow(2, 53) - 1
:
900719925474099<b><em>1</em></b> == 900719925474099<b><em>3</em></b> // false
【讨论】:
我猜99007199254740992
通过代理是不安全的,当您知道这绝对是您想要使用的值时,不一定是不安全的数字。【参考方案2】:
唯一靠近另一个数字的数字 当与它的下一个数字相比时显示为真
9007199254740992 == 9007199254740993
true
9007199254740993 == 9007199254740994
false
9007199254740991 == 9007199254740992
false
9007199254740997 == 9007199254740998
false
【讨论】:
您的“假”结果都跨越了 2 的倍数边界,奇数是较低的。如果你比较一个偶数和下一个更大的数,比如2^53 + 4
和2^53 + 5
,你会发现它们在 IEEE754 双精度中是相等的。【参考方案3】:
我对这个问题也有同样的担忧。 -2^53~2^53
(包括边界值),而-2^53+1~2^53-1
。
终于在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger找到了正确的解释
它说,“安全”的意思是:
-
可以精确地表示为 IEEE-754 双精度数,并且
其 IEEE-754 表示不能是对任何其他整数进行四舍五入以适应 IEEE-754 表示的结果。
所以2^53
不是安全整数,因为:
它可以在 IEEE-754 中精确表示,但整数 2^53 + 1
不能在 IEEE-754 中直接表示,而是在四舍五入和四舍五入下舍入到 2^53
。
【讨论】:
以上是关于为啥 Number.MAX_SAFE_INTEGER 是 9,007,199,254,740,991 而不是 9,007,199,254,740,992?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?