简体   繁体   中英

Cannot understand how add operation works on decimal numbers in javascript

I have always been coding in java and have recently started coding in javascript (node.js to be precise). One thing that's driving me crazy is add operation on decimal numbers;

Consider the following code

var a=0.1, b=0.2, c=0.3;
var op1 = (a+b)+c;
var op2 = (b+c)+a;

To my amazement I find out op1 != op2 ! console.logging op1 and op2 print out the following:

console.log(op1); 0.6000000000000001
console.log(op2); 0.6

This does not make sense. This looks like a bug to me because javascript simply cannot ignore rules of arithmetic. Could someone please explain why this happens?

This is a case of floating-point error.

The only fractional numbers that can be exactly represented by a floating-point number are those that can be written as an integer fraction with the denominator as a power of two.

For example, 0.5 can be represented exactly, because it can be written 1/2. 0.3 can't.

In this case, the rounding errors in your variables and expressions combined just right to produce an error in the first case, but not in the second case.

Neither way is represented exactly behind the scenes, but when you output the value, it rounds it to 16 digits of precision. In one case, it rounded to a slightly larger number, and in the other, it rounded to the expected value.

The lesson you should learn is that you should never depend on a floating-point number having an exact value , especially after doing some arithmetic.

That is not a javascript problem, but a standard problem in every programming language when using floats. Your sample numbers 0.1, 0.2 and 0.3 cannot be represented as finite decimal, but as repeating decimal, because they have the divisor 5 in it: 0.1 = 1/(2*5) and so on. If you use decimals only with divisor 2 (like a=0.5, b=0.25 and c=0.125), everything is fine.

This happens because not all floating point numbers can be accurately represented in binary .

Multiply all your numbers by some number (for example, 100 if you're dealing with 2 decimal points).

Then do your arithmetic on the larger result.

After your arithmetic is finished, divide by the same factor you multiplied by in the beginning.

http://jsfiddle.net/SjU9d/

a = 10 * a;
b = 10 * b;
c = 10 * c;

op1 = (a+b)+c;
op2 = (b+c)+a;

op1 = op1 / 10;
op2 = op2 / 10;

When working with floats you might want to set the precision on the numbers before you compare.

(0.1 + 0.2).toFixed(1) == 0.3

However, in a few cases toFixed doesn't behavior the same way across browsers. Here's a fix for toFixed.

http://bateru.com/news/2012/03/reimplementation-of-number-prototype-tofixed/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM