views:

2452

answers:

15
0.1 + 0.2 == 0.3  
// returns false

0.1 + 0.2 
// returns 0.30000000000000004

Any ideas why this happens?

+61  A: 

All floating point math is like this and is based on the IEEE standard.

You need to never compare with == but instead compare the absolute value of their differences, and make sure that this difference is smaller than the Epsilon value, which is a very very small number.

x = 0.2;
y = 0.3;
equal = (Math.abs(x - y) < 0.000001)

For the exact reason why, please read this paper.

Brian R. Bondy
'Some error constant' also known as an Epsilon value.
Gary Willoughby
@Gary Thanks for the info. I edited the answer and added a link to "Machine epsilon" in Wikipedia.
Patrick McElhaney
I think "some error constant" is more correct than "The Epsilon" because there is no "The Epsilon" which could be used in all cases. Different epsilons need to be used in different situations. And the machine epsilon is almost never a good constant to use.
Rotsor
@Rotsor couldn't agree more. I think linking to machine epsilon adds confusion - it's really something else.
Peter
+1  A: 

Floating point numbers.

TheTXI
I think there was a < 14sec difference in the post time of this vs. the +8. That's pretty harsh
TheTXI
+1, we all posted this at nearly the same time.
Ed Swangren
+1  A: 

They are floats.

Ed Swangren
Why the downvote eh?
Ed Swangren
@Ed: Probably because our posts were seen as copies of the top vote getter, even though all our posts were made within less than a minute of one another.
TheTXI
Seriously, leave a comment if you think this is wrong. The OP is more than capable of figuring out what floating point numbers are.
Ed Swangren
@Ed: I voted you up anyway. No reason to get punished just because one answer went in 15 seconds faster.
TheTXI
I voted you up too. now you should be back to zero.
Chandan .
Awwww...thanks guys.
Ed Swangren
yeah, -4 + 20 = +16 :-)
Chandan .
+19  A: 

Floating point rounding errors. 0.1 cannot be represented as accurately in base-2 as in base-10 due to the missing prime factor of 5. Just as 1/3 takes an infinite number of digits to represent in decimal, but is "0.1" in base-3, 0.1 takes an infinite number of digits in base-2 where it does not in base-10. And computers don't have an infinite amount of memory.

Devin Jeanpierre
+2  A: 

Floating point variables typically have this behaviour. It's caused by how they are stored in hardware.

For more info check out the Wikipedia article on floating point numbers.

Ben S
+6  A: 

JavaScript treats decimals as floating point numbers, which means operations like addition might be subject to rounding error.

You might want to take a look at this article: What Every Computer Scientist Should Know About Floating-Point Arithmetic

matt b
What about non decimal numbers?
Pablo Cabrera
Integers are treated as well, integers
matt b
Just for information, ALL numeric types in javascript are IEEE-754 Doubles.
Gary Willoughby
@Gary True, although you are guaranteed to have perfect integer precision for integers up to 15 digits, see http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference
Ender
+2  A: 

Floating point rounding error. From http://docs.sun.com/source/806-3568/ncg_goldberg.html:

Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation. Although there are infinitely many integers, in most programs the result of integer computations can be stored in 32 bits. In contrast, given any fixed number of bits, most calculations with real numbers will produce quantities that cannot be exactly represented using that many bits. Therefore the result of a floating-point calculation must often be rounded in order to fit back into its finite representation. This rounding error is the characteristic feature of floating-point computation.

Brett Daniel
+5  A: 

When you convert .1 or 1/10 to base 2 (binary) you get a repeating pattern after the decimal point, just like trying to represent 1/3 in base 10. The value is not exact, and therefore you can't do exact math with it using normal floating point methods.

Joel Coehoorn
Nice concise answer!
Patrick McElhaney
+3  A: 

Try rounding it off using toFixed().

(0.1 + 0.2).toFixed(1) == 0.3
Patrick McElhaney
+1  A: 

Don't forget the comp.lang.javascript FAQ which covers this and many other questions.

Jason S
+3  A: 

Yes, it's 'broken', and is proposed to be fixed in the next version with support for decimal numeric values.

Pete Kirkham
+3  A: 

In addition to the other correct answers, you may want to consider scaling your values to avoid problems with floating-point arithmetic.

For example:

var result = 1.0 + 2.0;     // result === 3.0 returns true

... instead of:

var result = 0.1 + 0.2;     // result === 0.3 returns false

The expression 0.1 + 0.2 === 0.3 returns false in JavaScript, but fortunately integer arithmetic in floating-point is exact, so decimal representation errors can be avoided by scaling.

As a practical example, to avoid floating-point problems where accuracy is paramount, it is recommended1 to handle money as an integer representing the number of cents: 2550 cents instead of 25.50 dollars.


1 Douglas Crockford: JavaScript: The Good Parts: Appendix A - Awful Parts (page 105).

Daniel Vassallo
+1  A: 

All numbers in JavaScript are represented in binary as IEEE-754 Doubles, which provides an accuracy to about 14 or 15 significant digits. Because they are floating point numbers, they do not always exactly represent real numbers, including fractions.

http://en.wikipedia.org/wiki/JavaScript_syntax#Number

Gary Willoughby
+1  A: 

I asked this question myself with different wording bc I didn't know to look for "floating-point". I would suggest tagging it with "decimals" and "fractions" "addition subtraction". If I search for "javascript adding decimals inaccurate", the search mechanism isn't smart enough to equate "decimals" with "floating-point" and "adding" with "math".

Greg Perham
Good-enough suggestion. This answer will also help future searches, with those terms, hit this question.
Brock Adams
A: 

A solution to tidy up the unsightly overflow

function strip(number) {
    return (parseFloat(number.toPrecision(12)));
}

Using 'toPrecision(12)' leaves trailing zeros which 'parseFloat()' removes. Assume it is accurate to plus/minus one on the least significant digit.

linux_mike