classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Problems with float Math.min(float,float) etc


From: Eric Blake
Subject: Re: Problems with float Math.min(float,float) etc
Date: Tue, 15 Jan 2002 09:37:18 -0700

Peter Dickerson wrote:
> 
> Math.min(float,float) seems to have incorrect behaviour for negative zero.
> 

You must have a stale file.  I show CVS to have this already (which
avoids a method call, and does not have the bug you mentioned):

  public static float min (float a, float b)
  {
    // this check for NaN, from JLS 15.21.1, saves a method call
    if (a != a)
      return a;
    // no need to check if b is NaN; < will work correctly
    // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special
    if (a == 0 && b == 0)
      return -(-a - b);
    return (a < b) ? a : b;
  }

However, I did notice some similar problems in Double and Float, and am
checking in the following patch.

-- 
This signature intentionally left boring.

Eric Blake             address@hidden
  BYU student, free software programmer
2002-01-15  Eric Blake  <address@hidden>

        * java/lang/Double.java (equals, compare): Fix 0.0 vs. -0.0 math.
        * java/lang/Float.java (equals, compare): Ditto.

Index: java/lang/Double.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Double.java,v
retrieving revision 1.26
diff -u -r1.26 Double.java
--- java/lang/Double.java       15 Nov 2001 02:23:35 -0000      1.26
+++ java/lang/Double.java       15 Jan 2002 16:34:04 -0000
@@ -1,5 +1,5 @@
 /* Double.java -- object wrapper for double primitive
-   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -44,7 +44,8 @@
  *
  * @author Paul Fisher
  * @author Andrew Haley <address@hidden>
- * @since JDK 1.0
+ * @author Eric Blake <address@hidden>
+ * @since 1.0
  */
 public final class Double extends Number implements Comparable
 {
@@ -163,9 +164,12 @@
     if (!(obj instanceof Double))
       return false;
 
-    Double d = (Double) obj;
+    double d = ((Double) obj).value;
 
-    return doubleToLongBits (value) == doubleToLongBits (d.doubleValue ());
+    // common case first, then check NaN and 0
+    if (value == d)
+      return (value != 0) || (1 / value == 1 / d);
+    return isNaN(value) && isNaN(d);
   }
 
   /**
@@ -336,10 +340,9 @@
       return isNaN (y) ? 0 : 1;
     if (isNaN (y))
       return -1;
-    if (x == 0.0d && y == -0.0d)
-      return 1;
-    if (x == -0.0d && y == 0.0d)
-      return -1;
+    // recall that 0.0 == -0.0, so we convert to infinites and try again
+    if (x == 0 && y == 0)
+      return (int) (1 / x - 1 / y);
     if (x == y)
       return 0;
 
Index: java/lang/Float.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Float.java,v
retrieving revision 1.21
diff -u -r1.21 Float.java
--- java/lang/Float.java        11 Nov 2001 16:07:09 -0000      1.21
+++ java/lang/Float.java        15 Jan 2002 16:34:04 -0000
@@ -1,5 +1,5 @@
 /* java.lang.Float
-   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -44,7 +44,8 @@
  *
  * @author Paul Fisher
  * @author Andrew Haley <address@hidden>
- * @since JDK 1.0
+ * @author Eric Blake <address@hidden>
+ * @since 1.0
  */
 public final class Float extends Number implements Comparable
 {
@@ -232,9 +233,12 @@
     if (!(obj instanceof Float))
       return false;
 
-    Float f = (Float) obj;
+    float f = ((Float) obj).value;
 
-    return floatToIntBits (value) == floatToIntBits (f.floatValue ());
+    // common case first, then check NaN and 0
+    if (value == f)
+      return (value != 0) || (1 / value == 1 / f);
+    return isNaN(value) && isNaN(f);
   }
 
   /**
@@ -484,10 +488,9 @@
       return isNaN (y) ? 0 : 1;
     if (isNaN (y))
       return -1;
-    if (x == 0.0 && y == -0.0)
-      return 1;
-    if (x == -0.0 && y == 0.0)
-      return -1;
+    // recall that 0.0 == -0.0, so we convert to infinities and try again
+    if (x == 0 && y == 0)
+      return (int) (1 / x - 1 / y);
     if (x == y)
       return 0;
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]