The post on
http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/

describes a (on first sight) trivial bug when parsing strings into
Java Double objects.

Runtime (java app hang):

class runhang {
public static void main(String[] args) {
  System.out.println("Test:");
  double d = Double.parseDouble("2.2250738585072012e-308");
  System.out.println("Value: " + d);
 }
}

DevTime (javac hang):

class compilehang {
public static void main(String[] args) {
  double d = 2.2250738585072012e-308;
  System.out.println("Value: " + d);
 }
}

The problem is that the estimation of halfUlp is too small in the case where
the larger alternative is normal and the smaller is denormal.  In this case,
the first estimate for

2.22507385850720120e-308 is

2.225073858507200889...e-308, an error of -3.109754e-324

and the second is

2.225073858507201383...e-308, an error of 1.830902e-324

so the second should be chosen.  Unfortunately, in the second case the
calculated halfUlp is 2^-1076, which is wrong because the next lower number
will be denormal.  Because denormals don't have the implied 1 bit, they are
less accurate than normals, so the next lower number will have the same
precision as this number, not twice the precision.  Therefore, the estimated
halfUlp is too large: it must be 2^-1075.

So, I think this may be the correct fix:

--- /local/openjdk/jdk6/jdk/src/share/classes/sun/misc/FloatingDecimal.java
2011-02-01 15:28:10.550913741 +0000
+++
/local/icedtea6/openjdk/jdk/src/share/classes/sun/misc/FloatingDecimal.java2011-02-02
12:07:22.292913754 +0000
@@ -1549,7 +1548,7 @@
                 if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
                     overvalue = true; // our candidate is too big.
                     diff = bigB.sub( bigD );
-                    if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){
+                    if ( (bigIntNBits == 1) && (bigIntExp-1 > -expBias) ){
                         // candidate is a normalized exact power of 2 and
                         // is too big. We will be subtracting.
                         // For our purposes, ulp is the ulp of the

Andrew.

Reply via email to