Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
254 views
in Technique[技术] by (71.8m points)

javascript - Number.prototype.toFixed: amazingly correct in Internet Explorer

Consider the following:

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

What? No, no surprise here. That's rather obvious, see: Number literal 2.175 is actually stored in memory (by IEEE-754 rules) as a value that's just a tiny little bit smaller than 2.175. And that's easy to prove:

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

That's how it works in the latest versions of Firefox, Chrome, and Opera on 32-bit Windows setup. But that's not the question.

The real question is how Internet Explorer 6 (!) actually manages to do it right as humans do:

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

OK, I overdramatized: actually all Internet Explorers I tested this on (IE8-11, and even MS Edge!) behave the same way. Still, WAT?

UPDATE: It gets stranger:

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

Why the difference - in all but the last one? And why no difference in the last one? It's very similar for x=0.1; while(x-=0.01)..., by the way: until we get very close to zero, toFixed in IE apparently attempts to cut some corners.

Disclaimer: I do know that floating-point math is kinda flawed. What I don't understand is what's the difference between IE and the rest of the browser's world.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The reported behavior deviates from the requirements of the ECMA specification.

Per clause 8.5, the Number type has the IEEE-754 64-bit binary values, except there is only one NaN. So 2.175 cannot be represented exactly; the closest you can get is 2.17499999999999982236431605997495353221893310546875.

Per 15.7.4.5, toFixed(20) uses an algorithm that boils down to:

  • “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.”
  • In the above, f is 20 (the number of digits requested), and x is the operand, which should be 2.17499999999999982236431605997495353221893310546875.
  • This results in selecting 217499999999999982236 for n.
  • Then n is formatted, producing “2.17499999999999982236”.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...