Why is it that some numbers in scientific notation starting with 9.999999999999999 get rounded to 1 while others remain the same?
For example, in Google Chrome 20 the following happens.
(9.999999999999999e+306).toString() === "9.999999999999999e+306" // true
but
(9.999999999999999e+303).toString() === "1e+304" // true
Why is that? Is it a floating point issue?
However the strangest thing is that in Opera 11.64 (1e23).toString() === "9.999999999999999e+22". I tried to report the 1e23 bug to Opera but no one replied.
Live Demo Here:
http://jsfiddle.net/3ekDK/3/
Source code of Demo
var console = console || {};
console.logToBody = function( str ){
document.body.innerHTML += "" + str + "<br/>";
};
var parts = ["9.999999999999999e", 310 ], tmp, tmp2;
while( parts[1]-- ){
tmp = +(parts.join(''));
if( /9.9{3,}e/.test( +tmp ) ){
console.logToBody( tmp + " doesn't convert to " + (+tmp).toPrecision(1) );
}
tmp2 = "1e"+parts[1];
//Carakan Javascript Engine Math BUG:
if( !/^1e*/.test( +tmp2 ) ){
console.logToBody( tmp2 + " = " + (+tmp2) + " in the runtime environment.");
}
}
It’s because floating point numbers are sometimes an approximation. Some numbers can’t be represented by the floating point format, that is, a binary fraction, so they are approximated http://en.wikipedia.org/wiki/IEEE_754-2008
That is why you should never rely on floating point arithmetic without rounding it. A simple example is the following:
Here’s a great explanation of the floating point format http://www.randelshofer.ch/fhw/gri/float.html#chapterfloatingpointformat
Ordinary Decimal 178.125
Scientific Decimal 1.78125 E 102
Scientific Binary 1.0110010001 E 2111