groovy
  1. groovy
  2. GROOVY-3309

comparisons with NaN should always return false

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.5.7, 1.6-rc-2
    • Fix Version/s: 3.0
    • Component/s: groovy-runtime
    • Labels:
      None
    • Environment:
      os x, jse 5 and 6
    • Number of attachments :
      0

      Description

      The following assertions should all pass; the third fails.

      assert !(Double.NaN == 0)
      assert !(Double.NaN < 0)
      assert !(Double.NaN > 0)

      A NaN should also not equal a NaN.

      assert Double.NaN != Double.NaN

        Activity

        Guillaume Laforge made changes -
        Field Original Value New Value
        Fix Version/s 1.6.1 [ 14852 ]
        Fix Version/s 1.5.8 [ 14630 ]
        Fix Version/s 1.7-beta-1 [ 14014 ]
        Hide
        Roshan Dawrani added a comment -

        Comparisons that groovy is doing is through calls to Double.compare(..) in this case:

        In Java too:
        Double.compare(Double.NaN, 0) //returns 1, indicating NaN > 0
        Double.compare(Double.NaN, Double.NaN) //returns 0, indicating NaN and NaN are equal.

        However:
        Double.NaN < 0 //returns false
        Double.NaN > 0 //returns false
        Double.NaN == Double.NaN // returns false

        So, does it mean that even in Groovy, if Double.NaN, Float.NaN are involved, they should be treated differently before the comparison reaches Double.compare(..) / Float.compare(..), etc?

        Show
        Roshan Dawrani added a comment - Comparisons that groovy is doing is through calls to Double.compare(..) in this case: In Java too: Double.compare(Double.NaN, 0) //returns 1, indicating NaN > 0 Double.compare(Double.NaN, Double.NaN) //returns 0, indicating NaN and NaN are equal. However: Double.NaN < 0 //returns false Double.NaN > 0 //returns false Double.NaN == Double.NaN // returns false So, does it mean that even in Groovy, if Double.NaN, Float.NaN are involved, they should be treated differently before the comparison reaches Double.compare(..) / Float.compare(..), etc?
        Hide
        blackdrag blackdrag added a comment - - edited

        compareTo supports returning a positive value (for example +1), a negative value (for example -1) or zero. Now if Double.NAN<=>0 must not return 0, then that leaves +1 or .-1. If we also say Double.NAN<=>0 must not return -1, then it must return +1 or throw an exception. Andy seems to suggest that compare returns neither +1, 0 nor -1, which leaves the exception as only possibility. The javadoc of compareTo says:

        • Double.NaN is considered by this method to be equal to itself and greater than all other double values (including Double.POSITIVE_INFINITY).
        • 0.0d is considered by this method to be greater than -0.0d.

        This ensures that Double.compareTo(Object) (which forwards its behavior to this method) obeys the general contract for Comparable.compareTo, and that the natural order on Doubles is consistent with equals.

        So they wanted to define an order on Double including NAN to avoid exceptions and decided that NAN is to be handled as a special value bigger than POSITIVE_INFINITY. This has the advantage, that if you sort a list of doubles for example, then you have to check for invalid doubles before. They are not invalid because they are NAN, they would be invalid if they would throw an exception while comparing.

        You may say that a comparable Double.NAN is mathematically more correct, on the other hand I can easily define a correct math for this.

        But it seems there is a problem, because a double NaN and a Double NaN behave different.If I do Double.NaN==Double.NaN in Java, then it will return false. This is according to IEEE 754 correct. The only comparision of Double.NaN with another double that return true is Double.NaN!=Double.NaN. So Double.compareTo behaves much different from normal primitive double operations. If we want to follow the primitive operations we have to adapt the Groovy version of comparing Double numbers.

        And I suggest to follow the primitive doubles of Java here

        Show
        blackdrag blackdrag added a comment - - edited compareTo supports returning a positive value (for example +1), a negative value (for example -1) or zero. Now if Double.NAN<=>0 must not return 0, then that leaves +1 or .-1. If we also say Double.NAN<=>0 must not return -1, then it must return +1 or throw an exception. Andy seems to suggest that compare returns neither +1, 0 nor -1, which leaves the exception as only possibility. The javadoc of compareTo says: Double.NaN is considered by this method to be equal to itself and greater than all other double values (including Double.POSITIVE_INFINITY). 0.0d is considered by this method to be greater than -0.0d. This ensures that Double.compareTo(Object) (which forwards its behavior to this method) obeys the general contract for Comparable.compareTo, and that the natural order on Doubles is consistent with equals. So they wanted to define an order on Double including NAN to avoid exceptions and decided that NAN is to be handled as a special value bigger than POSITIVE_INFINITY. This has the advantage, that if you sort a list of doubles for example, then you have to check for invalid doubles before. They are not invalid because they are NAN, they would be invalid if they would throw an exception while comparing. You may say that a comparable Double.NAN is mathematically more correct, on the other hand I can easily define a correct math for this. But it seems there is a problem, because a double NaN and a Double NaN behave different.If I do Double.NaN==Double.NaN in Java, then it will return false. This is according to IEEE 754 correct. The only comparision of Double.NaN with another double that return true is Double.NaN!=Double.NaN. So Double.compareTo behaves much different from normal primitive double operations. If we want to follow the primitive operations we have to adapt the Groovy version of comparing Double numbers. And I suggest to follow the primitive doubles of Java here
        Guillaume Laforge made changes -
        Fix Version/s 1.6.1 [ 14852 ]
        Fix Version/s 1.6.2 [ 15151 ]
        Guillaume Laforge made changes -
        Fix Version/s 1.5.8 [ 14630 ]
        Guillaume Laforge made changes -
        Fix Version/s 1.6.2 [ 15151 ]
        Fix Version/s 1.6.3 [ 15251 ]
        Guillaume Laforge made changes -
        Fix Version/s 1.6.3 [ 15251 ]
        Guillaume Laforge made changes -
        Fix Version/s 1.7-beta-1 [ 14014 ]
        Fix Version/s 1.7-beta-x [ 15538 ]
        blackdrag blackdrag made changes -
        Fix Version/s 1.8.x [ 15750 ]
        Fix Version/s 2.x [ 17013 ]
        Fix Version/s 1.7.x [ 15538 ]
        blackdrag blackdrag made changes -
        Fix Version/s 3.0 [ 13489 ]
        Fix Version/s 1.8.x [ 15750 ]
        Fix Version/s 2.x [ 17013 ]
        blackdrag blackdrag made changes -
        Component/s groovy-runtime [ 16250 ]

          People

          • Assignee:
            Unassigned
            Reporter:
            Andy Fyfe
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated: