Big Moose Saloon
 Search | Java FAQ | Recent Topics Register / Login

Fernando Dominguez
Ranch Hand

Joined: Sep 01, 2006
Posts: 99

Hello,
I'm trying to add to Doble numbers with 2 decimal places, 12,25 + 23, 46 = 35, 71
I get most of the time.
But some times, for example, 12,10 + 20,15 gets 32,24999999999999999999996
Why?

Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19423

13

Because floating point numbers are not precise enough, in the same sense that 1/3 is not precise enough when written in decimals. Check out http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

The simple solution is to use ints representing the numbers times 100 (can be useful when dealing with adding / subtracting simple money values; the ints then represent the cents), or more intuitively use BigDecimal.

SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
Karsten Daemen
Greenhorn

Joined: Nov 19, 2009
Posts: 19
Fernando Dominguez wrote:Hello,
I'm trying to add to Doble numbers with 2 decimal places, 12,25 + 23, 46 = 35, 71
I get most of the time.
But some times, for example, 12,10 + 20,15 gets 32,24999999999999999999996
Why?

I'm a student engineer, no java expert at all but I can tell you a bit about numerical math:

A simple sum like 12,10 + 20,15 that gets 32,24999999999999999999996 is impossible in my opinion.

Rounding errors like these can come however from for example:
Endless numbers like pi and 0.99999999...., they will only be saved to about 16 numbers exact (I think) and therefore have some rounding errors.
Doing multiple operations with such numbers can result increase these rounding errors.
Doing operations with really small numbers is also verry unstable.

It's not java's fault, it's just the way computers work with numbers. You have to search for a more "Numerical stable" algorithm.

Using the BigDecimal class for your operations can also solve the problem because you will then save your numbers to more places exact.

I hope this very short intro to numerical math answered a bit of your question.

Give me golf clubs, fresh air and a beautiful partner, and you can keep the clubs and the fresh air.
Jesper de Jong
Java Cowboy
Bartender

Joined: Aug 16, 2005
Posts: 13554

6

Java's float and double data types are stored in IEEE 754 floating point format. Such floating-point number have a limited number of bits (32 bits for a float, 64 bits for a double) and therefore can't store numbers with arbitrary precision.

IEEE 754 floating point numbers are stored as binary fractions. Some numbers simply cannot be represented with a finite number of digits by a binary fraction, just like some numbers like 1/3 cannot be represented by a finite number of digits as a decimal fraction.

If you need arbitrary precision, use BigDecimal instead of float or double.

Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19423

13

Karsten, you are mostly right, but if you read the Wiki article I linked to you will see that even numbers like 0.1 cannot be represented exactly on computers. Being binary, only 1/2 and multiples of it can be represented exactly, and the sum of them. So something like 0.625, which is 0.5 + 0.125 or 1/2 + 1/8, can be represented exactly, but just like many natural fractions cannot be represented perfectly in the decimal system (1/3, 2/7, etc), many decimal numbers cannot be represented perfectly in the binary system. With the example, 12.10 is as much an approximation in binary as 1/3 is in decimal, and therefore there will indeed be rounding errors.

And you are most definitely right that this is not Java's fault. The same will happen in almost every programming language, since the problem is caused by the underlying system.

I agree. Here's the link: http://aspose.com/file-tools