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
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?