编程语言
首页 > 编程语言> > 用JavaScript或IEEE-754舍入怪癖?

用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 of n ÷ 10fx is as close to zero as possible. If there are two such n, pick the larger n.

和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