Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / April 2004

Tip: Looking for answers? Try searching our database.

Trouble with a double

Thread view: 
Princess Morgiah - 19 Apr 2004 21:57 GMT
Hi everyone,

Why does this
 for (double x = 0.80; x < 1.0; x += 0.01)
 {
  System.out.println("Threshold " + x);
 }
give me the following result:
Threshold 0.8
Threshold 0.81
Threshold 0.8200000000000001
Threshold 0.8300000000000001
Threshold 0.8400000000000001
Threshold 0.8500000000000001
Threshold 0.8600000000000001
Threshold 0.8700000000000001
Threshold 0.8800000000000001
Threshold 0.8900000000000001
Threshold 0.9000000000000001
Threshold 0.9100000000000001
Threshold 0.9200000000000002
Threshold 0.9300000000000002
Threshold 0.9400000000000002
Threshold 0.9500000000000002
Threshold 0.9600000000000002
Threshold 0.9700000000000002
Threshold 0.9800000000000002
Threshold 0.9900000000000002

I can understand that there is a deviation from the expected value, but why
not in the first two cases?

Thanks in advance,

Princess Morgiah
VisionSet - 19 Apr 2004 22:41 GMT
> Hi everyone,
>
[quoted text clipped - 27 lines]
> I can understand that there is a deviation from the expected value, but why
> not in the first two cases?

Because the error (due to the fact binary cannot represent decimal fractions
accurately) is cumulative and the error initially is not sufficient to
register in the 64 bit representation.

Signature

Mike W

Bryce (Work) - 19 Apr 2004 22:55 GMT
>Hi everyone,
>
[quoted text clipped - 24 lines]
>Threshold 0.9800000000000002
>Threshold 0.9900000000000002

Someone answered this better than I could... But I'd suggest if you
want to keep a 2 decimal place number, try using one of the Decimal
classes...

>I can understand that there is a deviation from the expected value, but why
>not in the first two cases?
>
>Thanks in advance,
>
>Princess Morgiah

--
now with more cowbell
Yoyoma_2 - 20 Apr 2004 03:03 GMT
>>Hi everyone,
>>
[quoted text clipped - 7 lines]
>>Threshold 0.81
>>Threshold 0.8200000000000001

> Someone answered this better than I could... But I'd suggest if you
> want to keep a 2 decimal place number, try using one of the Decimal
> classes...

And that was me hihihi.

Ok here's the deal.  With double numbers you are not guaranteed the
"precision" of the number.  This is also called "Machine Epsilon" and
you can look it up on google.

Basically for a 32 bit machine it works out that you can only guarantee
a number to 10^-9 decimal places, for a 64bit its 10^-12 if i remember
correctly.

You aren't guaranteed that 0.8 + 0.1 = 0.9.  It could be 0.899999999999
or 0.900000000001 as you magically observed.

Its a normal side-effect of the way floating point numbers are
calculated on-chip.

If you want a large number of places, then you can use BigDouble or
BigInt.

This is the same reason you can't do an if directly on a double.

For example "if( myVal == 0.81 )" in your case would return false since
myVal = 0.81000000000001 which is != 0.81

To do this all you have to do is get the machine epsilon (the smallest
number that the CPU can distinguish from zero) and do the test like this.

if( myVal - epsilon >0 ){

}

But since you want to output these numbers, i reccomend using a
NumberFormat to strip your superfluous digits.

If you are taking computer science or an engineering disciplin, ask your
teacher he will tell you all about it.  There are ways to calculate for
this error and take it into account.  Very important when doing
engineering work where public liability is at stake.

If not then you can check out "Machine Epsilon" on google and you will
have all the info you need.

Good luck!

>>I can understand that there is a deviation from the expected value, but why
>>not in the first two cases?
[quoted text clipped - 5 lines]
> --
> now with more cowbell
Thomas Schodt - 20 Apr 2004 21:44 GMT
> I'd suggest if you
> want to keep a 2 decimal place number, try using one of the Decimal
> classes...

Personally, in this case, I'd probably just go for the simpler

for (int x=80;x<100;++x) {
   System.out.println("Threshold " + (x*.01) );
}
Eric Sosman - 20 Apr 2004 22:26 GMT
> > I'd suggest if you
> > want to keep a 2 decimal place number, try using one of the Decimal
[quoted text clipped - 5 lines]
>     System.out.println("Threshold " + (x*.01) );
> }

   ... which produces this output:

Threshold 0.8
Threshold 0.81
Threshold 0.8200000000000001
Threshold 0.8300000000000001
Threshold 0.84
Threshold 0.85
Threshold 0.86
Threshold 0.87
Threshold 0.88
Threshold 0.89
Threshold 0.9
Threshold 0.91
Threshold 0.92
Threshold 0.93
Threshold 0.9400000000000001
Threshold 0.9500000000000001
Threshold 0.96
Threshold 0.97
Threshold 0.98
Threshold 0.99

   Any more suggestions?

   (I've got one: See java.text.Format and its descendants.)

Signature

Eric.Sosman@sun.com

Princess Morgiah - 21 Apr 2004 22:03 GMT
> > > I'd suggest if you
> > > want to keep a 2 decimal place number, try using one of the Decimal
[quoted text clipped - 5 lines]
> >     System.out.println("Threshold " + (x*.01) );
> > }

Would this do the trick then?
System.out.println("Threshold " + (float) x / 100);
gives
Threshold 0.8
Threshold 0.81
Threshold 0.8200000000000001
Threshold 0.8300000000000001
Threshold 0.84
Threshold 0.85
Threshold 0.86
Threshold 0.87
Threshold 0.88
Threshold 0.89
Threshold 0.9
Threshold 0.91
Threshold 0.92
Threshold 0.93
Threshold 0.9400000000000001
Threshold 0.9500000000000001
Threshold 0.96
Threshold 0.97
Threshold 0.98
Threshold 0.99

Or am I missing something else here?

Thanks to everyone who replied!

Princess Morgiah
Carl Howells - 22 Apr 2004 00:07 GMT
> Or am I missing something else here?

You're missing every time someone has told you to look at the classes in
the java.text package.

In particular, look at java.text.DecimalFormat.  It has a constructor
that takes a string that lets you set its output format, and a method
format(double d) which produces a String from d, in the given format.
Princess Morgiah - 22 Apr 2004 20:08 GMT
> > Or am I missing something else here?
>
> You're missing every time someone has told you to look at the classes in
> the java.text package.

You assume that. I did have a look at those classes, yet found nothing of
importance that would help me, therefor I posted another possible solution.

> In particular, look at java.text.DecimalFormat.  It has a constructor
> that takes a string that lets you set its output format, and a method
> format(double d) which produces a String from d, in the given format.

"Which produces a String" indeed, in which I am not interested. I want to
use the resulting double value, for which I can see no possible way to get
to via the DecimalFormat class, part from possibly a very wordy construct
involving the parse method.

Therefor I ask what is wrong with
for (int x=80;x<100;++x) {
   System.out.println("Threshold " + (x*.01) );
}

which gives me the correct result - or at least appears to do so.

Thanks,

Princess Morgiah
Carl Howells - 22 Apr 2004 21:17 GMT
> "Which produces a String" indeed, in which I am not interested. I want to
> use the resulting double value, for which I can see no possible way to get
> to via the DecimalFormat class, part from possibly a very wordy construct
> involving the parse method.

Ahh..  That's important.  I didn't realize, and I suspect most people
reading the thread also didn't realize, that you wanted to continue
treating the values as doubles.  In your example, you only were
displaying them, which led me to believe the wrong thing.

In that case, it seems what you're looking for is a general set of rules
for working with floating point types to minimize cumulative error.  I
don't know of any, offhand, but I can confirm that what you're doing in
the case you listed is correct.

If only Patricia Shannahan (Did I spell that right?) was still following
this newsgroup....  She was the best I ever saw at explaining how
floating-point types work in the real world.  Unfortunately, her web
page doesn't have anything about the topic up.
Andrew Thompson - 22 Apr 2004 22:03 GMT
> If only Patricia Shannahan (Did I spell that right?) ..

No double 'nn', Shanahan.

Signature

Andrew Thompson
http://www.PhySci.org/ Open-source software suite
http://www.PhySci.org/codes/ Web & IT Help
http://www.1point1C.org/ Science & Technology

Mark Haase - 20 Apr 2004 01:44 GMT
> I can understand that there is a deviation from the expected value, but why
> not in the first two cases?

Certain fractions become repeating decimals in binary. Just like 1/3 in
decimal is .33333333333, etc. When you convert back to decimal, these
repeating fractions can leave behind odd artifacts.

|\/|  /|  |2  |<
mehaase(at)sas(dot)upenn(dot)edu
Tom - 20 Apr 2004 20:10 GMT
It stems from the fact that .1 is a repeating decimal when translated to binary.

> Hi everyone,
>
[quoted text clipped - 31 lines]
>
> Princess Morgiah
Roedy Green - 22 Apr 2004 01:54 GMT
>Why does this
>  for (double x = 0.80; x < 1.0; x += 0.01)
>  {
>   System.out.println("Threshold " + x);
>  }
see http://mindprod.com/jgloss/floatingpoint.html

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.