四舍五入怪癖在JavaScript或IEEE-754?(Rounding quirk in Java

2019-08-02 09:35发布

我遇到一个奇怪的问题,在我的单元测试给我带来了在JavaScript中意外舍入的结果之一:

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

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

起初我怀疑这是一个Webkit的只是在壁虎的问题,但它repros这意味着,我认为这是任何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的一部分,或者它们有一个bug。

Answer 1:

如果说明书没有因为改变修订版6的ECMA 262草案(5.1版,2011年3月), (2.005).toFixed(2)必须返回字符串"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 的F - x是接近零越好。 如果有两个这样的n ,挑大n

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

此外,并非它意味着很多,但IE9轮次如我所料,这意味着它要么是不是ECMA-262的一部分,或者它们有一个bug。

一个错误。 也许他们试图去简单的方法,并与乘10^digits和圆。 x*100正好是200.5 ,这样就会产生一个字符串"2.01"



文章来源: Rounding quirk in JavaScript or IEEE-754?