谁能给我解释一下为什么 9999999999999999 被转换成 10000000000000000?
alert(9999999999999999); //10000000000000000
谁能给我解释一下为什么 9999999999999999 被转换成 10000000000000000?
alert(9999999999999999); //10000000000000000
Javascript 没有整数,只有 64 位浮点数 - 而且您已经用完了浮点精度。
在 Java 中看到类似的问题:为什么 Double.parseDouble 使 9999999999999999 变为 10000000000000000?
JavaScript 只有浮点数,没有整数。
总结:浮点数只包括有限的精度,超过 15 位(左右),你会得到四舍五入。
9999999999999999
在 JavaScript 内部被视为浮点数。它无法在 IEEE 754 双精度中准确表示,因为它需要 54 位精度(位数为 log2(9999999999999999) = 53,150849512...并且由于小数位不存在,结果必须向上四舍五入)而 IEEE 754 仅提供 53 位(1 个隐式位 + 52 个显式存储的尾数位)——少了一位。因此,数字只是四舍五入。
由于在这种情况下仅丢失一位,因此即使是 54 位数字也可以准确表示,因为它们仍然包含0
在丢失的位中。给定 IEEE 754 的默认无偏舍入模式,奇数 54 位数字被舍入到最接近的值,该值恰好是偶数 53 位数字的两倍。
为什么 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 数字的非常详细的信息。
问题:有时 JavaScript 计算似乎会产生“不准确”的结果,例如 0.362*100 会产生 36.199999999999996。我怎样才能避免这种情况?
答:JavaScript 在内部以双精度浮点格式存储所有数字,带有 52 位尾数和 11 位指数(用于存储数值的 IEEE 754 标准)。数字的这种内部表示可能会导致如上所述的意外结果。大多数大于 253 = 9007199254740992 的整数无法以这种格式准确表示。同样,许多小数/分数(例如 0.362)无法准确表示,从而导致上述示例中的感知“不准确”。为了避免这些“不准确”的结果,您可能希望将结果四舍五入到您使用的数据的精度。