用JavaScript或IEEE-754舍入怪癖?

mck*_*mey 4 javascript math ieee-754

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

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

(2.00501).toFixed(2)
// produces "2.01"
Run Code Online (Sandbox Code Playgroud)

最初我怀疑这是一个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的一部分,要么就是它们有一个bug.

Dan*_*her 7

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

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

7.8.3和8.5中规定了数字文字的解释,以符合IEEE 754"舍入到最接近"模式(带有四舍五入到偶数有效),这样就2.005得到了数值

x = 4514858626438922 * 2^(-51) = 2.00499999999999989341858963598497211933135986328125
Run Code Online (Sandbox Code Playgroud)

在涉及的第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.

一个bug.也许他们试图采用简单的方式,并且与之相乘10^digits.x*100确切地说200.5,这将产生一串"2.01".