rai*_*7ow 20 javascript floating-point internet-explorer
考虑以下:
var x = 2.175;
console.log(x.toFixed(2)); // 2.17
Run Code Online (Sandbox Code Playgroud)
什么?不,这并不奇怪.这是相当明显的,请参阅:数字文字2.175实际上存储在内存中(通过IEEE-754规则)作为一个稍微小于2.175的值.这很容易证明:
console.log(x.toFixed(20)); // 2.17499999999999982236
Run Code Online (Sandbox Code Playgroud)
这就是它在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
Run Code Online (Sandbox Code Playgroud)
好吧,我过度使用了:实际上我测试过的所有Internet Explorer(IE8-11,甚至是MS Edge!)的行为方式都是一样的.还是,WAT?
更新:它变得陌生:
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
Run Code Online (Sandbox Code Playgroud)
为什么差异 - 除了最后一个?为什么最后一个没有区别?x=0.1; while(x-=0.01)...顺便说一下,它非常相似:直到我们非常接近零,toFixed在IE中显然试图削减一些角落.
免责声明:我不知道,浮点数学是有点缺陷.我不明白的是IE和浏览器世界其他部分之间的区别.
报告的行为偏离了ECMA规范的要求.
根据第8.5节,该Number类型具有IEEE-754 64位二进制值,除了只有一个NaN.所以2.175无法准确表示; 你最接近的是2.17499999999999982236431605997495353221893310546875.
根据15.7.4.5,toFixed(20)使用一种归结为:
我很欣赏埃里克的贡献,但是,在充分尊重的情况下,它没有回答这个问题.我承认我对那些"正确"和"令人惊讶的正确"短语过于厚颜无耻; 但是,我明白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
Run Code Online (Sandbox Code Playgroud)
在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"
Run Code Online (Sandbox Code Playgroud)