# Double troubles - Java

This is a discussion on Double troubles - Java ; Hi There is code fragment: BigDecimal bd = new BigDecimal(&quot;9999999999.999999&quot;); System.out.println(bd.toString()); double d = 9999999999.999999D; System.out.println(d); DecimalFormat f = (DecimalFormat) NumberFormat.getInstance(Locale.US); String s = f.format(d); System.out.println(s); f.setMinimumFractionDigits(6); s = f.format(d); System.out.println(s); Here is the result: 9999999999.999999 - good result 9.999999999999998E9 ...

1. ## Double troubles

Hi
There is code fragment:

BigDecimal bd = new BigDecimal("9999999999.999999");
System.out.println(bd.toString());

double d = 9999999999.999999D;
System.out.println(d);

DecimalFormat f = (DecimalFormat) NumberFormat.getInstance(Locale.US);
String s = f.format(d);
System.out.println(s);

f.setMinimumFractionDigits(6);
s = f.format(d);
System.out.println(s);

Here is the result:

9999999999.999999 - good result

9.999999999999998E9

10,000,000,000
~~~~~~~~~~~~~~~ precision loss

9,999,999,999.999998
~~~ precision loss

How can be avoided this precision loss in double ?

2. ## Re: Double troubles

Serhiy Brytskyy wrote:

<snip>
> 10,000,000,000
> ~~~~~~~~~~~~~~~ precision loss
>
> 9,999,999,999.999998
> ~~~ precision loss
>
> How can be avoided this precision loss in double ?

You can't. Welcome to floating points.

Every primitive type has a finite range and precision. As it happens,
double cannot represent 9999999999.999999 exactly. It is therefore
rounded to the nearest value that double can accommodate. Of course,
this value is in binary, and it isn't exactly 9999999999.999998 either,
but 9999999999.999998 is in turn the nearest to this value to six
decimal places.

If you need the greater precision, then you've practically answered your
own question: use BigDecimal.

Stewart.

--
My e-mail is valid but not my primary mailbox. Please keep replies on
the 'group where everyone may benefit.

3. ## Re: Double troubles

Ok, but see next:

C code

double d = 29.0 * 0.01;
printf("%f\n", d);
printf("%f\n", d * 100);

result:

0.290000
29.000000

Java code:
double d = 29.0 * 0.01;
System.out.println(d);
System.out.println((d * 100));

result

0.29
28.999999999999996

So, can we come to a conclusion that Java has buggy procedures with
floating point?

Stewart Gordon wrote:
> Serhiy Brytskyy wrote:
>
> <snip>
>
>> 10,000,000,000
>> ~~~~~~~~~~~~~~~ precision loss
>>
>> 9,999,999,999.999998
>> ~~~ precision loss
>>
>> How can be avoided this precision loss in double ?

>
>
> You can't. Welcome to floating points.
>
> Every primitive type has a finite range and precision. As it happens,
> double cannot represent 9999999999.999999 exactly. It is therefore
> rounded to the nearest value that double can accommodate. Of course,
> this value is in binary, and it isn't exactly 9999999999.999998 either,
> but 9999999999.999998 is in turn the nearest to this value to six
> decimal places.
>
> If you need the greater precision, then you've practically answered your
> own question: use BigDecimal.
>
> Stewart.
>

4. ## Re: Double troubles

On Thu, 16 Sep 2004 20:25:41 +0300, Serhiy Brytskyy wrote:
> Ok, but see next:
>
> C code
>
> double d = 29.0 * 0.01;
> printf("%f\n", d);
> printf("%f\n", d * 100);
>
> result:
>
> 0.290000
> 29.000000
>
> Java code:
> double d = 29.0 * 0.01;
> System.out.println(d);
> System.out.println((d * 100));
>
> result
>
> 0.29
> 28.999999999999996
>
>
> So, can we come to a conclusion that Java has buggy procedures with
> floating point?

No, at least not from what you've posted.

C again:

printf("%.15f\n",d);

result:
28.999999999999996

Oh wait, lets look a tiny bit closer:

printf("%.20f\n", d);
printf("%.20f\n", d * 100);
printf("%.20f\n", 0.01);

result:
0.28999999999999998002
28.999999999999996
0.01000000000000000021

Here's a clue: not all decimal numbers (e.g. 0.01) can be represented
exactly in base 2.

Here's another clue: what gets printed isn't always equal to the value
in memory.

And finally, a good source of more clues (warning: article contains
actual mathematics):

http://docs.sun.com/source/806-3568/ncg_goldberg.html

/gordon

--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e

5. ## Re: Double troubles

Ok, many thanks for detailed explanation.

Serhiy

Gordon Beaton wrote:
> On Thu, 16 Sep 2004 20:25:41 +0300, Serhiy Brytskyy wrote:
>
>>Ok, but see next:
>>
>>C code
>>
>>double d = 29.0 * 0.01;
>>printf("%f\n", d);
>>printf("%f\n", d * 100);
>>
>>result:
>>
>>0.290000
>>29.000000
>>
>>Java code:
>>double d = 29.0 * 0.01;
>>System.out.println(d);
>>System.out.println((d * 100));
>>
>>result
>>
>>0.29
>>28.999999999999996
>>
>>
>>So, can we come to a conclusion that Java has buggy procedures with
>>floating point?

>
>
> No, at least not from what you've posted.
>
> C again:
>
> printf("%.15f\n",d);
>
> result:
> 28.999999999999996
>
> Oh wait, lets look a tiny bit closer:
>
> printf("%.20f\n", d);
> printf("%.20f\n", d * 100);
> printf("%.20f\n", 0.01);
>
> result:
> 0.28999999999999998002
> 28.999999999999996
> 0.01000000000000000021
>
> So what's your point again?
>
> Here's a clue: not all decimal numbers (e.g. 0.01) can be represented
> exactly in base 2.
>
> Here's another clue: what gets printed isn't always equal to the value
> in memory.
>
> And finally, a good source of more clues (warning: article contains
> actual mathematics):
>
> http://docs.sun.com/source/806-3568/ncg_goldberg.html
>
> /gordon
>