You’ve been around javascript long enough to know there are some really strange quirks. Here is one I’ve not seen before. Consider very basic addition. If you want to try this just open your javascript console in Chrome or Firefox and simply enter:
4.3 + 8.0 + 6.15
Think the answer is 18.45? Wrong, you’ll get 18.450000000000003.
Ok, now lets rearrange those numbers and try it again:
4.3 + 6.15 + 8.0
Now you will get 18.45. After rearranging these some more and here are the results:
8.0 + 4.3 + 6.15 // 18.450000000000003 8 + 6.15 + 4.3 // 18.45 8.0 + 6.15 + 4.3 // 18.45 4.3 + 1 + 6.15 // 11.45 4.3 + 4 + 6.15 // 14.450000000000001 100 - (4.3 + 4 + 6.15) // 85.55 100 - 14.450000000000001 // 85.55
It seems to differ depending on the position within the addition sequence and also the numbers being added. So far these all round down, but what happens when you encounter this?
4.3 + 6.15 + 3.7 + 1.85 // 15.999999999999998 4.3 + 6.15 + 1.85 // 12.299999999999999
Ahh, now you run into some borderline issues. What if you are validating that you have $16?
16 == 4.3+6.15+3.7+1.85 // false 16 === 4.3+6.15+3.7+1.85 // false
So when do you know if you actually have 15.999999999999998 and when it is just a silly inconsistancy?
After some googling there are a few possible work arounds, like (8.0 + 4.3 + 6.15).toFixed(2) but you don’t always know how many decimal places you should need.
So you think this is just a silly client side validation issue? THINK AGAIN. This includes NodeJS as well, possibly others. This could be going into your database. Possibly over/under charging payments. Maybe you’re processing some type of precise calculations. If you know the number of decimal places you need you better ensure you’re rounding to that many decimal places.
Sure there is some fancy explanation (See http://floating-point-gui.de/), but is it broke? As far as I’m concerned, YES. Please, someone, prove me wrong!


10 Responses
t2n
Feb 25, 2013in python
>>> 4.3 + 8.0 + 6.15
18.450000000000003
>>> 4.3 + 6.15 + 8.0
18.45
>>>
solution:
https://github.com/dtrebbien/BigDecimal.js
Enrico
Feb 25, 2013This isn’t a javascript bug :)
If you do the same additions in C# you get the same results
I think it’s all about the x86 architecture
Álvaro G. Vicario
Feb 25, 2013That’s how computers work. Handling floating point numbers has two basic restrictions:
1.- Computers use base 2, not base 10
2.- Computers use a fixed size to store numbers
In your first example,
4.3 + 8.0 + 6.15, 4.3 has two digits in base 10 but it’s periodic in base 2 and something similar happens with 6.15. Only 8.0 has a exact representation in base 2 (please note it’s an integer).Broken? Well, 1/3 has a exact representation in base 3 but not in base 10. That doesn’t make base 10 broken.
You might enjoy this guide: What Every Programmer Should Know About Floating-Point Arithmetic
trent
Feb 25, 2013Right, I understand there is reasoning behind why it functions this way. Lets take a scenario. 90% of programmers developing a simple shopping cart would add their total with simply:
var total = 4.3 + 6.15 + 1.85;I guarantee very few of them will take into account these issues, and apply a work around, like rounding or converting the decimal dollar into cents so they are integers. Point of the article is you can’t simply trust it, you need to apply an approach to reassure the correct result.
Robert
Feb 26, 2013A programmer dealing with numbers that are inherently decimal, like currency, should know better than to use floating point math on those numbers. There’s really no excuse for not knowing how floating point math is implemented on computers (and “90% of programmers” don’t make a right).
Martijn
Feb 26, 2013Are you also one of those people who use FLOAT type columns in MySQL to store currency values? I can’t remember how many times I had to tell PHP “developers” not to do that.
Please excuse the sarcasm, but as Robert and others have pointed out, if you consider yourself a programmer, you should know how floats behave.
bungle
Feb 26, 2013Time to read about IEEE 754.
robert
Feb 26, 2013It’s not broken, trust me, I’m an engineer.
Have you ever noticed that in math classes you talk about real numbers but while programming you don’t have them but variables with type float? The programmers before you did a hell of a job making sure the arithmetic in your programs works really close to what you know from mathematics, and the fact that people can have a career in IT and think they are using real numbers just proves how well their idea works.
You should also be careful about big integers, since JS will convert big ones to floats, eg.:
9007199254740991+1 is 9007199254740992
but
9007199254740991+2 is still 9007199254740992
Reading:
http://en.wikipedia.org/wiki/Real_number
http://en.wikipedia.org/wiki/Floating-point_number
A lot of nice theory:
http://nm.mathforcollege.com/topics/floatingpoint_representation.html
trent
Feb 26, 2013@Robert, @Martijn
My point wasn’t that 90% makes it right, not at all. I even stated in the article there is a reason for it (though I don’t claim to be an expert), but the quick point was that developers need to use more assuring approaches, don’t just trust it.
XenoMuta
May 21, 2013Holy Microshit!!!!!!!
So, I was born again.
#include
int main (int argc, char *argv[]) {
printf("%0.32f\n", 4.3 + 8.0 + 6.15);
return 0;
}