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.
如果自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"
.