Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4191279

Float.toString() produces incorrect results

XMLWordPrintable

    • generic
    • generic

      Name: dkC59003 Date: 11/18/98



      This is almost same bug as reported in #4023198 (jdk 1.0.2, Float.toString
      produces incorrect results). Indeed 4023198 is closed, Float.toString()
      still continue to produce incorrect results for some other arguments.

      Error arises in following releases:

          JDK 1.0.2: fails under: solaris-sparc, win32
          JDK 1.1.x: fails under: solaris-x86 , win32
          JDK 1.2 : fails under: solaris-x86 (both with and without JIT)

      The problem is the following:

      JLS section 20.9.16 uniquely defines canonical result of Float.toString(x)
      for every float value x. However, the JDK releases listed above fail to
      produce correct result of Float.toString(x) for some particular values x.

      Below are the samples:

      ------------------------------------ fpm03504_bug.java:

      import java.lang.Float;

      class fpm03504_bug {

          static void main (String args[]) {
      float b59 = Float.intBitsToFloat(0x5d000000); // 2**59
      float b60 = Float.intBitsToFloat(0x5d800000); // 2**60
      float b61 = Float.intBitsToFloat(0x5e000000); // 2**61
      float b62 = Float.intBitsToFloat(0x5e800000); // 2**62

      String s59 = Float.toString(b59);
      String s60 = Float.toString(b60);
      String s61 = Float.toString(b61);
      String s62 = Float.toString(b62);

      String c59 = "5.7646075E17"; // canonical representations
      String c60 = "1.1529215E18"; // computed under JDK 1.2
      String c61 = "2.30584301E18"; // fcsR / solaris-sparc
      String c62 = "4.611686E18";

      boolean e59 = s59.compareTo(c59) == 0;
      boolean e60 = s60.compareTo(c60) == 0;
      boolean e61 = s61.compareTo(c61) == 0;
      boolean e62 = s62.compareTo(c62) == 0;

      System.out.println("b59: "+s59+"\t" + (e59? " -- Ok": " instead of: "+c59));
      System.out.println("b60: "+s60+"\t" + (e60? " -- Ok": " instead of: "+c60));
      System.out.println("b61: "+s61+"\t" + (e61? " -- Ok": " instead of: "+c61));
      System.out.println("b62: "+s62+"\t" + (e62? " -- Ok": " instead of: "+c62));
          }
      }

      ---------------------- produces under some JDK releases:

      java fpm03504_bug

      b59: 5.7646788E17 instead of: 5.7646075E17
      b60: 1.15293577E18 instead of: 1.1529215E18
      b61: 2.30587156E18 instead of: 2.30584301E18
      b62: 4.6116886E18 instead of: 4.611686E18

      --------------------------------------------------

      I have found, that b59,b60,b61,b62 are the only float values
      having the form 2**n, which bring Float.toString() to fail.

      ======================================================================

      Name: boT120536 Date: 01/22/2001


      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
      Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)


      The library routines for converting floats to Strings still have some bugs in
      them.

      According to the specs of Float.toString:
      "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 float. That is, suppose that x is the exact
      mathematical value represented by the decimal representation produced by this
      method for a finite nonzero argument f. Then f must be the float value nearest
      to x; or, if two float values are equally close to x then f must be one of them
      and the least significant bit of the significand of f must be 0."

      Take the number 123456789.0f. This rounds to the exact value 123456792 (the bit
      pattern 0x4ceb79a3, by Float.floatToIntBits). The nearest two floats
      are Float.intBitsToFloat(0x4ceb79a2), which is exactly 123456784, and
      Float.intBitsToFloat(0x4ceb79a4), which is exactly 1234567800.

      The representation 1.2345679E8 is closer to 123456792 than 123456784, so no
      further accuracy is allowed. However, System.out.println("" + 123456789f)
      produces 1.23456792E8, where the second digit '2' is spurious, according to the
      specs.
      (Review ID: 113581)
      ======================================================================
      ###@###.### 2004-11-11 21:42:37 GMT

            rgiulietti Raffaello Giulietti
            dkhukhrosunw Dmitry Khukhro (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: