Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different results when adding same doubles in different order

Why is the output different when adding same numbers?

public class Test {

    public static void main(String a[]) {

        double[] x = new double[]{3.9, 4.3, 3.6, 1.3, 2.6};
        System.out.println(">>>>>>> " + sum(x));
    }

    public static double sum(double[] d) {

        double sum = 0;
        for (int i = 0; i < d.length; i++) {
            sum += d[i];
        }
        return sum;
    }
}

Output is : 15.7

and if I interchange values

double[] x = new double[] {2.6, 3.9, 4.3, 3.6, 1.3};

I am getting Output as : 15.700000000000001

How do I get the same Output ?

like image 882
LMK Avatar asked Jan 27 '14 05:01

LMK


2 Answers

Floating point numbers lose precision as you do more operations. Generally, you get the highest precision by adding the smallest numbers first. (So the result does depend on the order of operations)

In addition to maintaining the same order of operations, you'll also have to use strictfp to get the same result on different platforms.

Or better yet, don't use floating points: use a BigDecimal instead.

like image 137
Navin Avatar answered Nov 07 '22 11:11

Navin


At each step in a sequence of floating point arithmetic operations, the system has to produce a result that is representable in the floating point format. That may lead to rounding error, the loss of some information.

When adding two numbers of different magnitudes, the larger one tends to control which bits have to be dropped. If you add a large and a small number, many bits of the small number will be lost to rounding error, because of the large magnitude of the result. That effect is reduced when adding numbers of similar magnitude. Adding several small numbers first, leaving the large magnitude numbers to the end, allows the effect of the small numbers to accumulate.

For example, consider { 1e17, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, -1e17 }. The exact answer, without any rounding, would be 147. Adding in the order shown above gives 112. Each addition of a "21.0" has to be rounded to fit in a number with magnitude around 1e17. Adding in ascending order of absolute magnitude gives 144, much closer to the exact answer. The partial result of adding the 7 small numbers is exactly 147, which then has to be rounded to fit in a number around 1e17.

like image 3
Patricia Shanahan Avatar answered Nov 07 '22 12:11

Patricia Shanahan