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 ?

有帮助吗?

解决方案

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.

其他提示

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.

Simply adding up all the values will lead to a comparatively large error for longer arrays anyhow (or more precisely: the error will be "large" when the sum already is "large", and further "small" numbers should be added).

As one possibility to reduce the numerical error, you might consider the http://en.wikipedia.org/wiki/Kahan_summation_algorithm :

public static double kahanSum(double d[])
{
    double sum = 0.0;
    double c = 0.0;
    for (int i=0; i<d.length; i++)
    {
        double y = d[i] - c;
        double t = sum + y;
        c = (t - sum) - y;
        sum = t;
    }
    return sum;        
}

because doubles and other floating-point data types have to deal with rounding issues when you perform operations. The precision is not infinite. If you divide 10/3, the result is 3.33333333... but the computer stores just part of this number.

check http://floating-point-gui.de/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top