Why do I get different answers multiplying three double values in a different order? [duplicate]

依然范特西╮ 提交于 2019-12-08 02:37:44

问题


I am executing the following code in java but i got two different answers for what should be the same number mathematically.

public class TestClass {

    public static void main(String[] args) {

        double a=0.01;
        double b=4.5;
        double c=789;       
        System.out.println("Value1---->"+(a*b*c));
        System.out.println("Value2---->"+(b*c*a));      
    }
}

Output:

Value1---->35.504999999999995
Value2---->35.505

Please tell me why I get this result.


回答1:


Floating point numbers have a certain precision. Some fractions can not be displayed correctly with floating point numbers, that's why rounding errors can occur.

The results are different because of the precedence of the calculations. Each of your calculations consists of two multiplications. The multiply * operator in Java has a left to right associativity. That means that in (a*b*c), a*b is calculated first and the multiplied by c as in ((a*b)*c). One of those calculation chains happens to produce a rounding error because a number in it simply can't be represented as a floating point number.




回答2:


Essentially, Java uses binary floating point values to handle all of its decimal based operations. As mentioned, in another answer, here is a link to the IEEE 754 that addresses the issue you've encountered. And as also mentioned in Joshua Bloch's Effective Java, refer to item 48 "Avoid float and double if exact answers are required":

In summary, don’t use float or double for any calculations that require an exact answer. Use BigDecimal if you want the system to keep track of the decimal point and you don’t mind the inconvenience and cost of not using a primitive type.




回答3:


It is because type double is an approximation. Double in Java denotes to IEEE 754 standart type decimal64. To resolve this problem use Math.round() or either BigDecimal class.




回答4:


'Cause double * double will be double, and that not totally precise.

Try the following code:

System.out.println(1.0-0.9-0.1) // -2.7755575615628914E-17

If you want totally precise real numbers, use BigDecimal instead!




回答5:


This is because double has finite precision. Binary representation can't store exactly the value of for example 0.01. See also wikipedia entry on double precision floating point numbers.

Order of multiplication can change the way that representation errors are accumulated.

Consider using BigDecimal class, if you need precision.




回答6:


As JavaDoc the double is a floating point type, and it's imprecise by nature. That why two exactly identical operation will wield different results, since the float point type (double) is an approximation.

See http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html :

double: The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. For decimal values, this data type is generally the default choice. As mentioned above, this data type should never be used for precise values, such as currency.

See also the wikipedia http://en.wikipedia.org/wiki/Floating_point :

The floating-point representation is by far the most common way of representing in computers an approximation to real numbers.




回答7:


http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html Quote: "double: The double data type is a double-precision 64-bit IEEE 754 floating point."
When you dig into IEEE 754 you will understand how doubles are stored in memory.
For such calculations I would recommend http://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html




回答8:


See this reply from 2011 Java:Why should we use BigDecimal instead of Double in the real world?

It's called loss of precision and is very noticeable when working with either very big numbers or very small numbers.

See the section

Decimal numbers are approximations

And read down




回答9:


Multiplication of floating points uses a process that introduces precision errors.

To quote Wikipedia:

"To multiply, the significands are multiplied while the exponents are added, and the result is rounded and normalized."

Java multiplies from left to right. In your example, the first parts (a * b and b * c) actually produce no precision errors.

So your final multiplications end up as:

System.out.println("Value1---->" + (0.045 * 789));
System.out.println("Value2---->" + (3550.5 * 0.01));

Now, 0.045 * 789 produces a precision error due to that floating point multiplication process. Whereas 3550.5 * 0.01 does not.




回答10:


As mentioned, there is an issue with the floating precision. You can either use printf or you can use Math.round() like so (change the number of zeros to affect precision):

System.out.println("Value 1 ----> " + (double) Math.round((a*b*c) * 100000) / 100000);
System.out.println("Value 2 ----> " + (double) Math.round((b*c*a) * 100000) / 100000);

Output

Value 1 ----> 35.505
Value 2 ----> 35.505



来源:https://stackoverflow.com/questions/29122007/why-do-i-get-different-answers-multiplying-three-double-values-in-a-different-or

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!