I have the following dummy test script:
function test() {
var x = 0.1 * 0.2;
document.write(x);
}
test();
This will print the result 0.020000000000000004
while it should just print 0.02
(if you use your calculator). As far as I understood this is due to errors in the floating point multiplication precision.
Does anyone have a good solution so that in such case I get the correct result 0.02
? I know there are functions like toFixed
or rounding would be another possibility, but I’d like to really have the whole number printed without any cutting and rounding. Just wanted to know if one of you has some nice, elegant solution.
Of course, otherwise I’ll round to some 10 digits or so.
14
From the FloatingPoint Guide:
What can I do to avoid this problem?
That depends on what kind of
calculations you’re doing.
 If you really need your results to add up exactly, especially when you
work with money: use a special decimal
datatype. If you just don’t want to see all those extra decimal places: simply
format your result rounded to a fixed
number of decimal places when
displaying it. If you have no decimal datatype available, an alternative is to work
with integers, e.g. do money
calculations entirely in cents. But
this is more work and has some
drawbacks.
Note that the first point only applies if you really need specific precise decimal behaviour. Most people don’t need that, they’re just irritated that their programs don’t work correctly with numbers like 1/10 without realizing that they wouldn’t even blink at the same error if it occurred with 1/3.
If the first point really applies to you, use BigDecimal for JavaScript, which is not elegant at all, but actually solves the problem rather than providing an imperfect workaround.
21
 12
I noticed your dead link for BigDecimal and while looking for a mirror, I found an alternative called BigNumber: jsfromhell.com/classes/bignumber
Dec 1, 2011 at 4:52
 5
@basst: Yes, but floats can exactly represent integers up to the length of the significand, and as per ECMA standard it’s a 64bit float. So it can exactly represent integers up to 2^52
Jul 25, 2012 at 13:15
 8
@Karl: The decimal fraction 1/10 cannot be represented as a finite binary fraction in base 2, and that’s what Javascript numbers are. So it is in fact exactly the same problem.
Dec 23, 2014 at 15:44
 22
I learned today that even integers have precision problems in javascript. Consider that
console.log(9332654729891549)
actually prints9332654729891548
(ie off by one!)– mlatheJul 10, 2015 at 21:01
 21
@mlathe: Doh..
;P
… Between2⁵²
=4,503,599,627,370,496
and2⁵³
=9,007,199,254,740,992
the representable numbers are exactly the integers. For the next range, from2⁵³
to2⁵⁴
, everything is multiplied by2
, so the representable numbers are the even ones, etc. Conversely, for the previous range from2⁵¹
to2⁵²
, the spacing is0.5
, etc. This is due to simply increasingdecreasing the baseradix 2binary exponent in/of the 64bit float value (which in turn explains the rarely documented ‘unexpected’ behavior oftoPrecision()
for values between0
and1
).Mar 2, 2016 at 19:42
I like Pedro Ladaria’s solution and use something similar.
function strip(number) {
return (parseFloat(number).toPrecision(12));
}
Unlike Pedros solution this will round up 0.999…repeating and is accurate to plus/minus one on the least significant digit.
Note: When dealing with 32 or 64 bit floats, you should use toPrecision(7) and toPrecision(15) for best results. See this question for info as to why.
11
 31
 27
toPrecision
returns a string instead of a number. This might not always be desirable.– SStanleyMar 13, 2016 at 23:42
 9
 5
@user2428118, I know, I meant to show the rounding error, The outcome is 1.00 instead of 1.01
– PeterJul 9, 2016 at 7:39
 14
What @user2428118 said may not be obvious enough:
(9.99*5).toPrecision(2)
= 50 instead of 49.95 because toPrecision counts the whole number, not just decimals. You can then usetoPrecision(4)
, but if your result is >100 then you’re out of luck again, because it’ll allow the first three numbers and one decimal, that way shifting the dot, and rendering this more or less unusable. I ended up usingtoFixed(2)
instead– mehovNov 15, 2018 at 11:38
For the mathematically inclined: http://docs.oracle.com/cd/E1995701/8063568/ncg_goldberg.html
The recommended approach is to use correction factors (multiply by a suitable power of 10 so that the arithmetic happens between integers). For example, in the case of 0.1 * 0.2
, the correction factor is 10
, and you are performing the calculation:
> var x = 0.1
> var y = 0.2
> var cf = 10
> x * y
0.020000000000000004
> (x * cf) * (y * cf) / (cf * cf)
0.02
A (very quick) solution looks something like:
var _cf = (function() {
function _shift(x) {
var parts = x.toString().split('.');
return (parts.length < 2) ? 1 : Math.pow(10, parts[1].length);
}
return function() {
return Array.prototype.reduce.call(arguments, function (prev, next) { return prev === undefined  next === undefined ? undefined : Math.max(prev, _shift (next)); }, Infinity);
};
})();
Math.a = function () {
var f = _cf.apply(null, arguments); if(f === undefined) return undefined;
function cb(x, y, i, o) { return x + f * y; }
return Array.prototype.reduce.call(arguments, cb, 0) / f;
};
Math.s = function (l,r) { var f = _cf(l,r); return (l * f  r * f) / f; };
Math.m = function () {
var f = _cf.apply(null, arguments);
function cb(x, y, i, o) { return (x*f) * (y*f) / (f * f); }
return Array.prototype.reduce.call(arguments, cb, 1);
};
Math.d = function (l,r) { var f = _cf(l,r); return (l * f) / (r * f); };
In this case:
> Math.m(0.1, 0.2)
0.02
I definitely recommend using a tested library like SinfulJS
7
 2
Il love this elegant workaround but seems not to be perfect: jsfiddle.net/Dm6F5/1 Math.a(76.65, 38.45) returns 115.10000000000002
Apr 16, 2014 at 12:29
 4
Math.m(10,2332226616) is giving me “19627406800” which is a negative value… I hope there must be a upper limit – might be that is causing this issue. Please suggest
Jul 15, 2014 at 6:07
 2
This all looks great, but seems to have a mistake or two in there somewhere.
– MrYellowMar 12, 2015 at 2:50
 10
 3
Don’t use the above code. It’s absolutely not a ‘quick solution’ if it does not work. This is a math related question, so accuracy is required.
– DrenaiJun 9, 2017 at 13:55
Actually, the error is because there is no way to map
0.1
to a finite binary floating point number.Sep 22, 2009 at 8:14
Most fractions can’t be converted to a decimal with exact precision. A good explanation is here: docs.python.org/release/2.5.1/tut/node16.html
Jan 10, 2011 at 18:35
possible duplicate of Is JavaScript’s Math broken?
Nov 2, 2011 at 3:18
@SalmanA: That your JavaScript runtime hides this problem from you doesn’t mean I’m wrong.
Nov 19, 2012 at 10:45
Disagree with Aaron, there are ways to code 0.1 perfectly and completely in binary. But IEEE 754 does not necessarily defines this. Imagine a representation where you would code the integer part in binary on the one hand, the decimal part on the other hand, up to n decimals, in binary too, like a normal integer > 0, and finally, the position of the decimal point. Well, you would represent 0.1 perfectly, with no error. Btw, since JS uses a finite number of decimals internally, they devs might as well coded the guts to not make that mistake on the last decimals.
Nov 14, 2016 at 5:59

Show 9 more comments