用JavaScript或IEEE-754舍入怪癖?
作者:互联网
我在我的一个单元测试中遇到了一个奇怪的问题,我在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的round-to-even方法?
任何人都想要了解一下在幕后发生的事情只是为了让我安心吗?
更新:感谢您的评论.
我应该补充一点,让我有点紧张的事情之一就是在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月)的Rev. 6以来没有改变,则(2.005).toFixed(2)必须返回字符串“2.00”,因为“数值”是
primitive value corresponding to a double-precision 64-bit binary format IEEE 754 value
7.8.3和8.5中规定了数字文字的解释,以符合IEEE 754“舍入到最接近”模式(带有四舍五入到偶数有效),这对于2.005导致值
x = 4514858626438922 * 2^(-51) = 2.00499999999999989341858963598497211933135986328125
在处理toFixed的第15.7.4.5节中,相关步骤8.是:
Let
n
be an integer for which the exact mathematical value ofn
÷ 10f –x
is as close to zero as possible. If there are two suchn
, pick the largern
.
和2.00 – x接近于零而不是2.01 – x,因此这里n必须是200.然后以自然的方式转换为字符串.
Also, not that it means much but IE9 rounds it as I expected, implying that it either isn’t part of ECMA-262 or they have a bug.
一个bug.也许他们试图采用简单的方法并乘以10 ^位数和圆形. x * 100正好是200.5,因此会产生一个“2.01”的字符串.
标签:javascript,math,ieee-754 来源: https://codeday.me/bug/20190901/1784438.html