The Artima Developer Community
Sponsored Link

Java Buzz Forum
1.03 - .42 = 0.6100000000000001? No Way!

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Weiqi Gao

Posts: 1808
Nickname: weiqigao
Registered: Jun, 2003

Weiqi Gao is a Java programmer.
1.03 - .42 = 0.6100000000000001? No Way! Posted: Jul 10, 2004 11:05 AM
Reply to this message Reply

This post originated from an RSS feed registered with Java Buzz by Weiqi Gao.
Original Post: 1.03 - .42 = 0.6100000000000001? No Way!
Feed Title: Weiqi Gao's Weblog
Feed URL: http://www.weiqigao.com/blog/rss.xml
Feed Description: Sharing My Experience...
Latest Java Buzz Posts
Latest Java Buzz Posts by Weiqi Gao
Latest Posts From Weiqi Gao's Weblog

Advertisement

For some reason, I can't seem to let this one go. I've read the comments on this blog (thanks Dan for all the information). I've talked with a few other people.

I have verified that Java and C++ represents the numbers 1.03, 0.42, and the result of 1.03 - 0.42 the same way by using

  • java.lang.Double.doubleToLongBits(double)
  • java.lang.Long.toHexString(long)

in Java and

  • double d, *p = &d;
  • long long l = *(reinterpret_cast<long long*>(p))

in C++.

So the differences are in the way doubles are printed.

Jeff Brown mentioned to me at the St. Louis JUG meeting Thursday that there might be other floating point numbers that Java prints right and other languages print wrong.

But a little experiment (a very superficial one, I admit) indicates that Java is wrong more times than C++:

[weiqi@gao] $ cat Foo.java
public class Foo {
  public static void main(String[] args) {
    double ds[] = {0.1, 0.2, 0.3, 0.4};
    for (int i = 0; i < 4; i++) {
      for (int j = i + 1; j < 4; j++) {
        System.out.println("" + ds[j] + "-" + ds[i] +
          "=" + (ds[j] - ds[i]));
      }
    }
  }
}
[weiqi@gao] $ javac Foo.java
[weiqi@gao] $ java Foo
0.2-0.1=0.1
0.3-0.1=0.19999999999999998
0.4-0.1=0.30000000000000004
0.3-0.2=0.09999999999999998
0.4-0.2=0.2
0.4-0.3=0.10000000000000003
[weiqi@gao] $ cat foo.cc
#include <iostream>
int main() {
  double ds[] = {0.1, 0.2, 0.3, 0.4};
  for (int i = 0; i < 4; i++) {
    for (int j = i + 1; j < 4; j++) {
      std::cout << ds[j] << "-" << ds[i] << "="
        << (ds[j] - ds[i]) << std::endl;
    }
  }
}
[weiqi@gao] $ make foo
g++     foo.cc   -o foo
[weiqi@gao] $ ./foo
0.2-0.1=0.1
0.3-0.1=0.2
0.4-0.1=0.3
0.3-0.2=0.1
0.4-0.2=0.2
0.4-0.3=0.1

Then Jeff Grigg interjected with the sarcastic "Java is right and everything else is wrong."

Somehow, I don't feel so confident.

The Javadoc for java.lang.Double.toString(double) details how Java prints a double. It specifically mentioned this:

How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double.

This might be the root of the problem. What if two adjacent doubles have decimal representations that differ only in insignificant digits? By the above rule, insignificant digits will be printed just so that the two numbers can be distinguished.

Does such pairs of adjacent doubles exist? I don't know. My suspicion is that they do exist, and 1.03 - .42 belongs to such a pair. Of course, it could also be something more complicated that I don't understand.

Read: 1.03 - .42 = 0.6100000000000001? No Way!

Topic: San Francisco Library Online: Free Access to O&#039;Reilly Safari Previous Topic   Next Topic Topic: Behind the curtain in the Keynote hall

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use