用JavaScript或IEEE-754舍入怪癖? [英] Rounding quirk in JavaScript or IEEE-754?

查看:127
本文介绍了用JavaScript或IEEE-754舍入怪癖?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've come across a curious issue in one of my unit tests where I'm getting unexpected rounding results in 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是否为指定了一种舍入方法

Initially I suspected this was a Webkit only issue but it repros in Gecko which implies to me that it is an expected side effect of either ECMA-262 or IEEE-754. I'm assuming the binary representation of 2.005 is ever so slightly less? Or does ECMA-262 specify a round-to-even methodology for toFixed?

任何人都需要提供一些见解关于发生什么事情只是为了让我安心?

Anyone care to shed some insight as to what is happening under the hood just to give me peace of mind?

更新:感谢您的评论。

我应该补充一下,让我有点紧张的一件事就是在Webkit快速搜索中发现的评论 dtoa.cpp 这似乎意味着有多条路径进行四舍五入,开发人员并不确定它是如何工作的,包括相关的 FIXME

I should add, one of the things that made me a little nervous was the comments found in a quick search in Webkit dtoa.cpp which seemed to imply that there were multiple paths to rounding and the devs weren't really sure how it worked, including a related FIXME:

https://trac.webkit .org / browser / trunk / Source / WTF / wtf / dtoa.cpp#L1110

此外,并不是说它意味着很多,但IE9将它作为我预期,暗示它不是ECMA-262的一部分或者它们有错误。

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.

推荐答案

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

If the specification hasn't changed since Rev. 6 of the ECMA 262 draft (edition 5.1, March 2011), (2.005).toFixed(2) must return the string "2.00", since a "Number value" is a


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

primitive value corresponding to a double-precision 64-bit binary format IEEE 754 value

并且在7.8.3和8.5中指定数字文字的解释以符合IEEE 754轮到最近的模式(带有四舍五入到偶数有效),对于 2.005 导致值

and the interpretation of numeric literals is specified in 7.8.3 and 8.5 to conform to IEEE 754 "round to nearest" mode (with ties rounded to even significand), which for 2.005 results in the value

x = 4514858626438922 * 2^(-51) = 2.00499999999999989341858963598497211933135986328125

在部分15.7.4.5处理 toFixed ,相关步骤8. a。是:

In section 15.7.4.5 which deals with toFixed, the relevant step 8. a. is:


n 是一个整数,其精确数学值 n ÷10 f - x 尽可能接近零。如果有两个这样的 n ,请选择较大的 n

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。然后以自然的方式转换为字符串。

and 2.00 - x is closer to zero than 2.01 - x, so n must be 200 here. The conversion to a string proceeds then in the natural way.


此外,并不是说它意味着很多,但是IE9按照我的预期对其进行了舍入,这意味着它要么不是ECMA-262的一部分,要么它们有错误。

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.

一个错误。也许他们试图采用简单的方法并乘以 10 ^位数并进行回合。 x * 100 正好是 200.5 ,因此会生成一个2.01的字符串

A bug. Maybe they tried to go the easy way and multiply with 10^digits and round. x*100 is exactly 200.5, so that would produce a string of "2.01".

这篇关于用JavaScript或IEEE-754舍入怪癖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆