confusing double behavior

This code:


double d = 0;
for (int i = 0; i < 100; i++) {

	d += 0.001 * i;

	System.out.println(d);

}

should output exact double values betwen 0.0 and 4.95.

but it gives me unexact values like:
0.0
0.0010
0.0030
0.0060
0.01
0.015
0.020999999999999998
0.027999999999999997
[…]
4.753000000000001
4.851000000000001
4.950000000000001

any ideas of why double addition is behaving in such an inexact way?

I had this very same question.

Some commonly used values, like 0.1, cannot be exactly expressed in floating point notation.
It sucks, but there you go.

then i’ll have to “round” values like 0.6 to “0.6” for a simple addition!?

that¡s great ¬¬

It doesn’t suck. Floating point numbers are not supposed to be used for exact calculations! This is the first thing anyone should know about them.

The reason is that internally computers work with the binary system. A fraction expressible with finitely many decimals in the decimal system may not be thus expressible in binary. You have the same problem in the decimal system.

If you want exact calculations, you will have to write (or borrow) some library which deals with rational numbers. Just converting to integers generally won’t help you, since you will still suffer from infinitely repeating fractions now and then.

By the way, floating point numbers are extremely powerful. Integers would use 32 bits to express all mathematical integers from minus two billion to plus two billion, which is fine. A floating point number has two parts:

  1. the mantissa (say, M), which generally uses most of the bits, which expresses decimals purely.
  2. the exponent (let’s call it q), which determines how large the value actually is.

A number is expressed by

M * 2^q,

and thanks to this notation, floating point numbers can be exceedingly large. With 32 bits distributed meaningfully between mantissa and exponent, you can express numbers as large as 10^38, though many adjacent mathematical integers in that range have the same floating point representation. With 64 bits you can reach something like 10^308.

(edit: minor corrections)

yeah i learned how to read and operate with numbers on fp on 1st year, but i’ve never faced this problem before. it is acurate anyway, so it is only a problem for displaying information.

It is not accurate. Use integers for any exact calculations.

Look up these classes…


NumberFormat
NumberFomatter

If you don’t specify the precision that you wish to use you end up seeing the full representation of how close the floating point number can come to the true value. Look at the significant digits and you can see that you probably don’t care in most cases that it is off by such a tiny amount - it is only the display that is a bother. So when the display matters, use a NumberFomatter or the newer Java 5 Formatting stuff to (printf even) to display the number.

acurate enought for a zoom factor, from 0.01 to 2.00