20

次の点を考慮してください。

var x = 2.175;
console.log(x.toFixed(2));  // 2.17

何?いいえ、驚くことではありません。これは明らかです。数値リテラル2.175は、実際には (IEEE-754 規則により) 2.175 よりほんの少し小さい値としてメモリに格納されます。そして、それは簡単に証明できます:

console.log(x.toFixed(20)); // 2.17499999999999982236

これが、32 ビット Windows セットアップ上の最新バージョンの Firefox、Chrome、Opera での動作です。しかし、それは問題ではありません。

本当の問題は、Internet Explorer 6 (!) が実際にそれをどのように行うかです。人間がするように:

var x = 2.175;
console.log(x.toFixed(2));  // 2.18
console.log(x.toFixed(20)); // 2.17500000000000000000

OK、誇張しました: 実際、これをテストしたすべての Internet Explorer (IE8-11、さらには MS Edge!) は同じように動作します。それでも、何?

更新:それは奇妙になります:

x=1.0;while((x-=0.1) > 0) console.log(x.toFixed(20));

IE                        Chrome
0.90000000000000000000    0.90000000000000002220
0.80000000000000000000    0.80000000000000004441
0.70000000000000010000    0.70000000000000006661
0.60000000000000010000    0.60000000000000008882
0.50000000000000010000    0.50000000000000011102
0.40000000000000013000    0.40000000000000013323
0.30000000000000015000    0.30000000000000015543
0.20000000000000015000    0.20000000000000014988
0.10000000000000014000    0.10000000000000014433
0.00000000000000013878    0.00000000000000013878

最後の違いを除いて、なぜ違いがあるのでしょうか。そして、なぜ最後のものに違いがないのですか?ちなみに、これは非常によく似ていx=0.1; while(x-=0.01)...ます。ゼロに非常に近づくまでtoFixed、IE では明らかにいくつかのコーナーをカットしようとします。

免責事項:浮動小数点演算には多少の欠陥があることは知っています私が理解していないのは、IE と他のブラウザーの世界との違いは何かということです。

4

3 に答える 3

8

エリックの貢献に感謝しますが、敬意を表して質問に答えません。私は、これらの「正しい」および「驚くほど正しい」フレーズで冗談を言いすぎたことを認めます。はい、IEの動作は実際には逸脱であることを理解しています。

ともかく。私はまだ IE の動作が異なる原因の説明を探していました。そして、皮肉なことに、Mozilla のトラッカーで、この長い議論の中で、ついに手がかりのように見えるものを見つけました。見積もり:

OUTPUT IN MOZILLA: 
a = 0.827 ==> a.toFixed(17) = 0.82699999999999996 
b = 1.827 ==> b.toFixed(17) = 1.82699999999999996

OUTPUT IN IE6: 
a = 0.827 ==> a.toFixed(17) = 0.82700000000000000 
b = 1.827 ==> b.toFixed(17) = 1.82700000000000000

IE と Mozilla で見られる違いは次のとおりです。IE は「a」を文字列として 保存し、Mozilla は「a」を値として保存しています。仕様は、ストレージ形式を特定していません。したがって、IE が行う場合a.toFixed、正確な文字列表現で開始されますが、Mozilla はラウンドトリップ変換に悩まされます。

これについて何らかの公式の確認が得られれば素晴らしいことですが、少なくとも私がこれまで見てきたことはすべて説明しています. 特に、

console.log( 0.3.toFixed(20) ); // 0.30000000000000000000
console.log( 0.2.toFixed(20) ); // 0.20000000000000000000
console.log( (0.3 - 0.2).toFixed(20) ); // "0.09999999999999998000"
于 2013-10-03T22:01:47.413 に答える