# Java double precision

Discussion in 'Java' started by info, Dec 7, 2004.

1. ### infoGuest

I know the following behaviour is an old problem,
but still I don't understand why such a simple piece of code:

double val = 0;
for(int i=0;i<10;i++) {
val+=0.1;
System.out.println(val);
}

has the following (terrible) output:

0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999

???

Why, as a developer, I have to use a trick like this to solve the
problem:

java.text.DecimalFormat df = new
java.text.DecimalFormat("###.########");
double val = 0;
for(int i=0;i<10;i++) {
val+=0.1;
val = df.parse(df.format(val)).doubleValue();
System.out.println(val);
}

Vincenzo Caselli

http://www.censnet.it

info, Dec 7, 2004

2. ### Michael BorgwardtGuest

Because double and float are internally represented as *binary* fractions
according to the IEEE standard 754
and can therefore not represent decimal fractions exactly.
http://mindprod.com/jgloss/floatingpoint.html
http://www.math.byu.edu/~schow/work/IEEEFloatingPoint.htm
*groan* You're 95% there and yet took the TOTALLY wrong turn at the last
intersection. You want to *format* numbers, so why are you using
DecimalFormat.parse()??? What do you think the format() method is for?

Furthermore, if you really need exact representation of decimal fractions
(usually the case only for financial applications), use java.math.BigDecimal.

Michael Borgwardt, Dec 7, 2004

3. ### waldGuest

wald, Dec 7, 2004
4. ### Patricia ShanahanGuest

There are two incompatible objectives for string conversion
of floating point data:

1. Produce a tidy result showing only meaningful digits.

2. Produce a result that uniquely identifies the floating
point number.

Language and library developers pick one for the default
conversion. In C, for example, printf aims for #1,
defaulting to 6 digit precision.

Java uses #2 as the default, producing enough digits to
ensure that the reverse conversion will recover the double.
The result of adding 0.1+0.1+0.1 really is different
from 0.3.

I don't fully understand the reason for your "trick". I
would have used the DecimalFormat when aiming for tidy
output, but would not have converted back or used the
result in continuing calculations. Doing so throws away
precision if the mathematical answer is not a short decimal
fraction. For example, try substituting 1/3.0 for 0.1 in

If you are only concerned with exact representation of short
decimal fractions, and don't need to deal with numbers like
1/3.0, consider using BigDecimal instead of double. Any
number that would be improved by your trick can be exactly
represented as a BigDecimal with scale=8.

Patricia

Patricia Shanahan, Dec 8, 2004
5. ### Chris SmithGuest

It's because you're thinking in decimal, but the computer thinks in
binary. 0.1 is a repeating decimal number in binary. To understand
this case, we could take an analogous algorithm in decimal; say, adding
1/3 instead of 1/10. In this example, we'll give the numbers ten
significant digits of precision, so:

0.3333333333
+ 0.3333333333
------------
= 0.6666666666
+ 0.3333333333
------------
= 0.9999999999

So the same thing happens with repeating decimal numbers in base 10 as
1/3 adds up. It's only counterintuitive because you're not expecting
0.1 to be a repeating decimal, and that's because you're not thinking in
base 2 like the computer is.
No, you can write:

DecimalFormat df = new DecimalFormat("###.########");
double val = 0;
for (int i = 0; i < 10; i++)
{
val += 0.1;
System.out.println(df.format(val));
}

As Patricia said, you're assuming that the "correct" answer is achieved
by truncating the result in decimal that then parsing it back again.
Only in the very limited case of nice round numbers is that true. This
would be a very poor idea if you were working with any kind of measured
or calculated quantity. You shouldn't be assuming enough precision that
rounding error will matter anyway, so there's no need to make that round
trip.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation

Chris Smith, Dec 10, 2004
6. ### soft

Joined:
Jun 10, 2009
Messages:
1
0
Hello, First of all, sorry for my ignorance. I have the following two questions:
1. Have the results showing in the program below anything to do with this discussion? I mean, is it the same problem?
2. Does my friend need to worry about this issue, if she is writing a program for a bank? :flute:

Can anyone explain what is happening below?

for(int i=0;i<20;i++)
System.out.println(i*1.26);

-----
0.0
1.26
2.52
3.7800000000000002
5.04
6.3
7.5600000000000005
8.82
10.08
11.34
12.6
13.86
15.120000000000001
16.38
17.64
18.9
20.16
21.42
22.68
23.94

soft, Jun 10, 2009