4

単体テストの 1 つで、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ますか?

私を安心させるためだけに、フードの下で何が起こっているのかについて洞察を提供してくれる人はいますか?

更新:コメントありがとうございます。

加えて、私が少し神経質になったことの 1 つは、Webkit のクイック検索で見つかったコメントでした。dtoa.cppこれは、丸めには複数のパスがあり、関連するFIXME:

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

また、それはあまり意味がありませんが、IE9 は期待どおりに丸めます。これは、ECMA-262 の一部ではないか、バグがあることを意味します。

4

1 に答える 1

8

ECMA262ドラフトのRev.6(エディション5.1、2011年3月)以降仕様が変更されていない場合、「数値」は文字列であるため(2.005).toFixed(2)、文字列を返す必要があります。"2.00"

倍精度64ビットバイナリ形式のIEEE754値に対応するプリミティブ値

数値リテラルの解釈は7.8.3および8.5で指定されており、IEEE 754の「最も近い値に丸める」モード(仮数に丸められたタイを使用)に準拠し2.005ます。

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

を扱うセクション15.7.4.5でtoFixed、関連するステップ8。は:

÷10f–の正確な数学的が可能な限りゼロに近いn整数とします。そのようなものが2つある場合は、大きい方を選択してください。nxnn

2.00 - xよりもゼロに近い2.01 - xので、nここでは200でなければなりません。文字列への変換は、自然な方法で進行します。

また、それは多くのことを意味するわけではありませんが、IE9は私が期待したようにそれを丸めます。これは、ECMA-262の一部ではないか、バグがあることを意味します。

バグ。10^digitsたぶん、彼らは簡単な方法で乗算し、ラウンドしようとしました。x*100は正確200.5にであるため、。の文字列が生成されます"2.01"

于 2012-11-07T00:46:38.430 に答える