2

这个 JavaScript 演示了 IE 中的一个错误,现在让我抓狂:

var y = 6044629098073143; // this exact integer easily fits into an IEEE double
document.write(y + " " + Math.round(y)+"<br><br>");

IE 8(和 Opera 12.02)中的输出显示Math.round了 1:

6044629098073143 6044629098073144

Firefox、Chrome 和 Safari 中的输出是正确的。

IE 和 Opera 到底发生了什么?

4

2 回答 2

3

我已经确认了 RobG 的评论:所有 2^52 (4503599627370496) 以下的整数似乎在所有浏览器中都正确舍入。在 IE/Opera 中使用 Math.round 将高于此值的整数向上舍入为偶数(而其他浏览器则正确舍入)。

正如 RobG 所提到的,IE 和 Opera 很可能将 Math.round(x) 实现为 Math.floor(x + 0.5),这会导致这些结果,因为将 0.5 添加到 > 2^52 的值会产生不精确的结果。更智能的 round() 实现将使用 FPU 的原生舍入支持(IE 和 Opera 开发人员,请注意并修复!)

同时,此解决方法应该有效:

// workaround for IE and Opera's brain-dead Math.round() implementation
if (y < 4503599627370496) // 2^52
{
  y = Math.round(y);
}
// else 'y' is already an integer
于 2012-10-11T19:07:42.510 回答
1

在 Opera an IE 中,保证工作的最大整数值是 4503599627370496 (2^52),如 RobG 在上面的评论中所述。

有趣的是,这也适用于某些部分的浮点值。对于大于此的数字,浮点数也会降低其准确性。
正如您在此处看到的,双精度数的尾数精度为 52 位。这意味着,对于所有大于 4503599627370496 的数字,最后一位数字将被修剪,因为尾数始终与所表示数字的最高有效位 (MSB) 对齐。

在 Opera 的控制台中输入:

//This works
>>> 4503599627370494.5 //Consumes 53 bits
4503599627370494.5
>>> 4503599627370495.5 //Consumes 53 bits
4503599627370495.5
//This works no more, the last bit is now needed
>>> 4503599627370496.5 //Consumes 54 bits
4503599627370496

这种准确性的损失解释了为什么这些浏览器没有准确的数字表示,最后一位只是简单地四舍五入。另请参阅Machine_epsilon。
不过,您可以从这个观察中得出结论,问题中显示的整数肯定会转换为双精度数。

于 2012-10-11T06:50:06.273 回答