Why does adding two decimals in Javascript produce a wrong result?

Possible Duplicate:
Is JavaScript’s Math broken?

Why does JS screw up this simple math?

console.log(.1 + .2)  // 0.3000000000000004
console.log(.3 + .6)  // 0.8999999999999999

The first example is greater than the correct result, while the second is less. ???!! How do you fix this? Do you have to always convert decimals into integers before performing operations? Do I only have to worry about adding (* and / don't appear to have the same problem in my tests)?

I've looked in a lot of places for answers. Some tutorials (like shopping cart forms) pretend the problem doesn't exist and just add values together. Gurus provide complex routines for various math functions or mention JS "does a poor job" in passing, but I have yet to see an explanation.

68286 次浏览

It has to do with how computers handle floating numbers. You can read more about it here: http://docs.sun.com/source/806-3568/ncg_goldberg.html

This is normal for all programming languages because not all decimal values can be represented exactly in binary. See What Every Computer Scientist Should Know About Floating-Point Arithmetic

This is not a javascript only limitation, it applies to all floating point calculations. The problem is that 0.1 and 0.2 and 0.3 are not exactly representable as javascript (or C or Java etc) floats. Thus the output you are seeing is due to that inaccuracy.

In particular only certain sums of powers of two are exactly representable. 0.5 = =0.1b = 2^(-1), 0.25=0.01b=(2^-2), 0.75=0.11b = (2^-1 + 2^-2) are all OK. But 1/10 = 0.000110001100011..b can only be expressed as an infinite sum of powers of 2, which the language chops off at some point. Its this chopping that is causing these slight errors.

From The Floating-Point Guide:

Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and instead I get a weird result like 0.30000000000000004?

Because internally, computers use a format (binary floating-point) that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.

When the code is compiled or interpreted, your “0.1” is already rounded to the nearest number in that format, which results in a small rounding error even before the calculation happens.

The site has detailed explanations as well as information on how to fix the problem (and how to decide whether it is a problem at all in your case).

It's not a JS problem but a more general computer one. Floating number can't store properly all decimal numbers, because they store stuff in binary For example:

0.5 is store as b0.1
but 0.1 = 1/10 so it's 1/16 + (1/10-1/16) = 1/16 + 0.0375
0.0375 = 1/32 + (0.0375-1/32) = 1/32 + 00625 ... etc


so in binary 0.1 is 0.00011...

but that's endless. Except the computer has to stop at some point. So if in our example we stop at 0.00011 we have 0.09375 instead of 0.1.

Anyway the point is, that doesn't depend on the language but on the computer. What depends on the language is how you display numbers. Usually, the language rounds numbers to an acceptable representation. Apparently JS doesn't.

So what you have to do (the number in memory is accurate enough) is just to tell somehow to JS to round "nicely" number when converting them to text.

You may try the sprintf function which give you a fine control of how to display a number.