为什么 9999999999999999 会转换为 10000000000000000 ?
JavaScript 中的所有数字都以 64 位格式 IEEE-754 存储,也称为“双精度”,因此正好有 64 位来存储一个数字:其中 52 位用于存储数字,其中11个存储小数点的位置(整数为零),1位用于符号。
如果一个数字太大,它会溢出 64 位存储,可能会导致
无穷大:
alert( 1e500 );
// Result => Infinity
// "e" multiplies the number by 1 with the given zeroes count.
如果我们检查 0.1 和 0.2 的和是否为 0.3,我们会得到错误。
alert( 0.1 + 0.2 == 0.3 )
奇怪!如果不是 0.3,那么它是什么? 这是因为,一个数字以二进制形式存储在内存中,即一系列 1 和 0。但是像 0.1、0.2 这样的分数在十进制数值系统中看起来很简单实际上是二进制形式的无休止分数。
换句话说,什么是 0.1?它是一除以十的 1/10,十分之一。在十进制数字系统中,这些数字很容易重新表示。将其与三分之一进行比较:1/3。它变成了一个无穷小数 0.33333(3)。
无法使用二进制系统准确存储 0.1 或 0.2,就像无法将三分之一存储为小数一样。
数字格式 IEEE-754 通过四舍五入到最接近的可能数字解决了这个问题。这些四舍五入规则通常不允许我们看到“微小的精度损失” ,所以数字显示为 0.3。但请注意,损失仍然存在。
如你所见:
alert( 9999999999999999 ); // shows 10000000000000000
这有同样的问题:精度损失。数字有 64 位,其中 52 位可用于存储数字,但 这还不够。所以最低有效数字消失了。
9999999999999999 到 10000000000000000 背后真正发生的事情是:
JavaScript 不会在此类事件中触发错误。它尽最大努力将数字拟合成所需的格式,但不幸的是,这种格式还不够大。
参考:https://javascript.info/number
你也可以参考这个SO Question,它包含了关于 JavaScript 编号的非常详细的信息。