Go Back   Velocity Reviews > Newsgroups > Java
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read


Reply

Java - Java double precision

 
Thread Tools Search this Thread
Old 12-07-2004, 08:54 AM   #1
info@censnet.it
 
Posts: n/a
Default Java double precision

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);
}


Thank you in advance
Vincenzo Caselli

http://www.censnet.it

  Reply With Quote
Old 12-07-2004, 09:11 AM   #2
Michael Borgwardt
 
Posts: n/a
Default Re: Java double precision

wrote:

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

[]
> has the following (terrible) output:

[]
> 0.7999999999999999
> 0.8999999999999999
> 0.9999999999999999
>
>
> ???


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/...atingPoint.htm

> 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);
> }


*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.
  Reply With Quote
Old 12-07-2004, 12:11 PM   #3
wald
 
Posts: n/a
Default Re: Java double precision

Michael Borgwardt <> wrote:

> http://mindprod.com/jgloss/floatingpoint.html


Another good explanation of what's happening under the hood is this
one:

http://en.wikipedia.org/wiki/Computer_numbering_formats

Wald
  Reply With Quote
Old 12-08-2004, 11:21 AM   #4
Patricia Shanahan
 
Posts: n/a
Default Re: Java double precision

wrote:
> 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);
> }
>
>
> Thank you in advance
> Vincenzo Caselli
>
> http://www.censnet.it
>


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
your test.

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





  Reply With Quote
Old 12-10-2004, 04:31 AM   #5
Chris Smith
 
Posts: n/a
Default Re: Java double precision

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


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
well. The cumulative error from adding 0.3333333333 instead of exactly
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.

> 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);
> }


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
  Reply With Quote
Old 06-10-2009, 11:10 AM   #6
soft
Junior Member
 
Join Date: Jun 2009
Posts: 1
Default

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?

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 is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
Java Beginners Still Bill Software 3 02-19-2008 09:13 AM
Segmentation Fault in C++ deltaone Software 0 08-02-2006 05:05 PM
Latest Tech Fiasco... Ghost A+ Certification 30 01-09-2004 11:15 AM
New Releases: Dilbert, Law&Order, Vacation: Updated complete downloadable R1 DVD DVB & info lists Doug MacLean DVD Video 1 07-24-2003 03:17 PM
New Releases: Paramount Discount, Fox Theme Packs: Updated complete downloadable R1 DVD DB & info lists Doug MacLean DVD Video 0 07-22-2003 04:33 AM




SEO by vBSEO 3.3.2 ©2009, Crawlability, Inc.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47