Double troubles - Java
This is a discussion on Double troubles - Java ; 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
...
-
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 ?
-
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.
-
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.
>
-
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
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
--
[ 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
-
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
>
Similar Threads
-
By Application Development in forum CSharp
Replies: 2
Last Post: 10-05-2007, 10:02 AM
-
By Application Development in forum DOTNET
Replies: 0
Last Post: 05-14-2007, 08:13 AM
-
By Application Development in forum basic.visual
Replies: 3
Last Post: 04-26-2005, 12:56 PM
-
By Application Development in forum C
Replies: 10
Last Post: 04-12-2004, 02:27 AM
-
By Application Development in forum basic.visual
Replies: 3
Last Post: 01-23-2004, 06:06 AM