Skip to content

Ordering methods are inconsistent for Double and Float #10511

Closed
@NthPortal

Description

@NthPortal

For:

  • Float.NaN
  • Double.NaN
  • -0.0f and 0.0f
  • -0.0d and 0.0d

the following inconsistencies exist:

  • Ordering.lt can return false when Ordering.compare returns a negative number
  • Ordering.lteq can return false when Ordering.compare returns a negative number or 0
  • Ordering.equiv can return false when Ordering.compare returns 0
  • Ordering.equiv can return true when Ordering.compare returns a non-zero value
  • Ordering.gteq can return false when Ordering.compare returns a positive number or 0
  • Ordering.gt can return false when Ordering.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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions