4

我在我的一个单元测试中遇到了一个奇怪的问题,我在 JavaScript 中得到了意想不到的舍入结果:

(2.005).toFixed(2)
// produces "2.00"

(2.00501).toFixed(2)
// produces "2.01"

最初我怀疑这是一个 Webkit 唯一的问题,但它在 Gecko 中重现,这对我来说意味着它是 ECMA-262 或 IEEE-754 的预期副作用。我假设 2.005 的二进制表示会稍微少一点?或者 ECMA-262 是否指定了一种四舍五入的方法toFixed

任何人都愿意对引擎盖下发生的事情有所了解,只是为了让我高枕无忧?

更新:感谢您的评论。

我应该补充一下,让我有点紧张的一件事是在 Webkit 中的快速搜索中发现的评论dtoa.cpp似乎暗示有多种舍入路径,开发人员并不确定它是如何工作的,包括相关的FIXME

https://trac.webkit.org/browser/trunk/Source/WTF/wtf/dtoa.cpp#L1110

此外,这并不是说它意义重大,而是 IE9 像我预期的那样对其进行了舍入,这意味着它不是 ECMA-262 的一部分,或者它们有一个错误。

4

1 回答 1

8

如果自ECMA 262 草案第6版(5.1 版,2011 年 3 月)以来规范没有更改,则(2.005).toFixed(2)必须返回 string "2.00",因为“数字值”是

对应于双精度 64 位二进制格式 IEEE 754 值的原始值

并且数字文字的解释在 7.8.3 和 8.5 中指定,以符合 IEEE 754“四舍五入到最接近”模式(关系四舍五入到偶数有效位),这2.005会导致值

x = 4514858626438922 * 2^(-51) = 2.00499999999999989341858963598497211933135986328125

在处理的第 15.7.4.5 节中toFixed,相关的步骤 8。是:

n是一个整数,其精确的数学值n÷ 10 fx尽可能接近于零。如果有两个这样n的,选择较大的n

2.00 - x比 更接近零2.01 - x,所以n这里必须是 200。然后以自然方式进行到字符串的转换。

此外,这并不是说它意义重大,而是 IE9 像我预期的那样对其进行了舍入,这意味着它不是 ECMA-262 的一部分,或者它们有一个错误。

一个错误。也许他们试图走简单的路并乘以10^digits和舍入。x*100正是200.5,所以会产生一串"2.01".

于 2012-11-07T00:46:38.430 回答