Description
For:
Float.NaN
Double.NaN
-0.0f
and0.0f
-0.0d
and0.0d
the following inconsistencies exist:
Ordering.lt
can return false whenOrdering.compare
returns a negative numberOrdering.lteq
can return false whenOrdering.compare
returns a negative number or0
Ordering.equiv
can return false whenOrdering.compare
returns0
Ordering.equiv
can return true whenOrdering.compare
returns a non-zero valueOrdering.gteq
can return false whenOrdering.compare
returns a positive number or0
Ordering.gt
can return false whenOrdering.compare
returns a positive number
The reason for the inconsistency is that the convenience methods are overridden to use the primitive operators (<
, <=
, ==
, >=
, and >
respectively), which always return false for operations where at one of the operands is NaN
. However compare
is implemented by java.lang.{Float, Double}.compare
, for which NaN
is ordered as larger than all other values. Also, the primitive operators treat -0.0
and 0.0
as equal, while java.lang.{Float, Double}.compare
do not.
Ordering.min
is inconsistent with compare
as well; however, I'm not sure it is consistent with the other methods either. Ordering.max
seems to be consistent with compare
by chance.
It is possible that this behavior is intended, though counter-intuitive, but if so, it should probably be documented.
One result of these inconsistencies is that TraversableOnce.min
and .max
are non-deterministic (and wrong):
scala> import java.lang.Double.NaN
import java.lang.Double.NaN
scala> Seq(5.0, 3.0, NaN, 4.0)
res0: Seq[Double] = List(5.0, 3.0, NaN, 4.0)
scala> res0.min
res1: Double = 4.0
scala> res0.max
res2: Double = 4.0
Those methods could be fixed by using Ordering.min
and .max
internally, instead of .lteq
and .gteq
; however, they shouldn't need to.