【问题标题】:JavaScript Math.round bug in IEIE 中的 JavaScript Math.round 错误
【发布时间】:2012-10-11 01:07:08
【问题描述】:

这段 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 到底发生了什么?

【问题讨论】:

  • 也许真的是一个 IE 错误?见dojotoolkit.org/reference-guide/1.8/dojo/number.html#round
  • 根据ECMA-262If x is already an integer, the result is x。但是,由于Math.round(6044629098073144) 在 IE 中返回了正确的值,并且随着数字的增加,它一直在正确和 +1 之间振荡(偶数是静态的,奇数是加一的),我怀疑你已经达到了连续 javascript 的限制整数。
  • 我们还没有达到连续 javascript 整数的限制(因为所有整数
  • 记录一下,IE中Math.round不加修改返回的最大连续整数是4503599627370496,也就是2^52,之后是2^52,说明有操作在drop一位精度,因为连续整数应该达到 2^53。所以绝对是一个错误。
  • 刚刚注意到 ECMA-262 还说“Math.round(x) 的值与 Math.floor(x+0.5) 的值相同”,所以也许这就是缺失位的地方正在运行,因为Math.floor(y + 0.5) 在 IE 中具有完全相同的行为。请注意,来自Math.round 的非整数的连续限制无论如何都是 2^52。所以可能不是错误,而是对规范的解释不同。

标签: javascript internet-explorer opera


【解决方案1】:

我已经确认 RobG 的 cmets:所有低于 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

【讨论】:

  • 使用本机 FPU 在实现中添加了额外的每个平台代码(许多默认/仅舍入为零,而不是舍入到正无穷大),尤其是。在根本没有 FPU 的情况下需要代码路径。
【解决方案2】:

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

有趣的是,这也适用于某些部分的浮点值。 对于大于此的数字,浮点数也会降低其准确性。
如您所见here,双精度数的尾数精度为 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.
不过,您可以从这个观察中得出结论,问题中显示的整数肯定会转换为双精度数。

【讨论】:

    猜你喜欢
    • 2011-11-18
    • 1970-01-01
    • 2014-10-03
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    相关资源
    最近更新 更多