Java sum of all double does not return expected result [duplicate]
Asked Answered
V

10

6

Possible Duplicate:
Moving decimal places over in a double

Why is the following sum of numbers not equal to 0.4622? but 0.46219999999999994

Double total = new Double(0.08) + new Double(0.0491) + new Double(0.3218) + 
         new Double(0.0113) + new Double(0.0); // = 0.46219999999999994

I have an application that checks the users input.

The user inputs 5 decimal numbers and a total number. The application checks if the sum of all 5 numbers capped at 4 decimals behind the komma is equal to the total number.

Capping it gives me 0.4621 which is not equal to 0.4622. I can't use DecimalFormat because it rounds it up. And if i explicitly say, round down then it will fail for this situation.

Any suggestion for how I can solve this?

Verdugo answered 8/1, 2013 at 14:53 Comment(2)
DecimalFormat does "round up" ? Are you sure ? From the javadoc : "DecimalFormat uses half-even rounding (see ROUND_HALF_EVEN) for formatting."Artificial
Rounding 0.46219999999999994 instead of just truncating goes give the right answer.. Regardless floating point operations are always notorious for their lack of exactness.Chromatic
A
13

Try with java.math.BigDecimal. Double rounds result. You will just have to use add method, not + operator.

Athanor answered 8/1, 2013 at 14:56 Comment(1)
Thank you for the information this helped me along with the "possible duplicate" from vishal_aimVerdugo
P
6

Avoid using float and double if exact answers are required-- Item 48 -- Effective Java Second edition

Use BigDecimal instead.

Panatella answered 8/1, 2013 at 14:56 Comment(0)
D
4

Double and float in Java are internally represented as binary fractions and can therefore be not precise in representing decimal fractions (IEEE standard 754). If your decimal number calculations require precision, use Java.math.BigDecimal.

Donny answered 8/1, 2013 at 15:0 Comment(0)
N
3

Looks like a classic case of floating point arithmetic. If you want exact calculations, use java.math.BigDecimal. Have a look at What Every Computer Scientist Should Know About Floating-Point Arithmetic

Nephelinite answered 8/1, 2013 at 14:57 Comment(0)
H
3

Floating point representation is a close approximation so you will have these little rounding errors when you use float and double. If you try to convert 0.08 to binary for instance you will realize that you cannot actually do it exactly. You need to consider this whenever you use double and float in calculations.

0.0810 = 0.00010100011110101110...2

a repeating pattern. So no matter how many bits you use this will have a rounding error.

Hypabyssal answered 8/1, 2013 at 14:57 Comment(0)
F
3

When you use floating point arithmetic you must also use appropriate rounding.

BTW: Don't use an object when a primitive will do.

double total = 0.08 + 0.0491 + 0.3218 + 0.0113 + 0.0;
System.out.printf("%.4f%n", total);

double rounded = Math.round(total * 1e4) / 1e4;
if (rounded == 0.4622)
    System.out.println("rounded matched");

prints

0.4622
rounded matched

as expected.

Filar answered 8/1, 2013 at 15:0 Comment(0)
B
2

That is yet another rounding issue. You should never compare doubles and expect them to be exactly equal. Instead define a small epsylon and expect the result to be within epsylon of the expected answer.

Bechance answered 8/1, 2013 at 14:56 Comment(0)
U
0

Any floating point value is inexact. The solution is to use DecimalFormat when you have to display the values. And no, it doesn't round up but to the nearest value.

From the javadoc :

DecimalFormat uses half-even rounding (see ROUND_HALF_EVEN) for formatting.

Underlaid answered 8/1, 2013 at 14:57 Comment(0)
G
0

The internal representation of floating point numbers like Double is never a exact one. This is why during calculations such errors can occur.

It is always suggested to format such a result to a specific number of digits past the comma, so you result would be correctly be display as "0.4622" with 4 to 15 or more digits.

Geisha answered 8/1, 2013 at 14:57 Comment(0)
O
0

Perhaps checking the string input directly would be more feasible for you. That is check the length of characters after the decimal place.

Oar answered 8/1, 2013 at 15:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.