мин / макс коллекций, содержащих NaN (обработка несопоставимости при заказе)

Я только что столкнулся с неприятной ошибкой в результате следующего поведения:

scala> List(1.0, 2.0, 3.0, Double.NaN).min
res1: Double = NaN

scala> List(1.0, 2.0, 3.0, Double.NaN).max
res2: Double = NaN

Я понимаю, что для парного сравнения иногда может быть предпочтительнее иметьmax(NaN, 0) = NaN и это, вероятно, причина, почемуjava.lang.Double.compare следует этому соглашению (кажется,Стандарт IEEE для этого). Однако для коллекции я действительно считаю, что это странное соглашение. Ведь вышеупомянутая коллекция действительно содержит действительные числа; и эти числа имеют четкий максимум и минимум. На мой взгляд, концепция о том, чтомаксимальное количество из коллекциине число противоречие, так как NaN не является числом, поэтому оно не может быть максимальным или минимальным «числом» коллекции - если только нет действительных чисел; в этом случае имеет смысл, что максимум "не число". Семантическиmin а такжеmax функции вырождаются, чтобы проверить, содержит ли коллекция NaN. Поскольку существуют более подходящие способы проверить наличие NaN (например,collection.find(_.isNaN)) было бы здорово поддерживать семантически значимый минимум / максимум в коллекциях.

Итак, мой вопрос: каков наилучший подход для получения поведения, позволяющего игнорировать существование NaN? Я вижу две возможности:

Фильтрация NaN перед вызовом мин / макс. Поскольку это требует явного решения проблемы во всех местах и может повлечь за собой снижение производительности, я бы предпочел что-то более простое.

Было бы замечательно иметь порядок упорядочения, игнорирующий NaN, который можно использовать как неявное упорядочение там, где это необходимо. Я попробовал следующее:

  object NanAwareOrdering extends Ordering[Double] {
    def compare(x: Double, y: Double) = {
      if (x.isNaN()) {
        +1 // without checking x, return y < x
      } else if (y.isNaN()) {
        -1 // without checking y, return x < y
      } else {
        java.lang.Double.compare(x, y)
      }
    }
  }

Тем не менее, этот подход, кажется, зависит от того, заинтересован ли я в поиске минимума или максимума, т.е.

 scala> List(1.0, 2.0, 3.0, Double.NaN).min(NanAwareOrdering)
 res7: Double = 1.0

 scala> List(1.0, 2.0, 3.0, Double.NaN).max(NanAwareOrdering)
 res8: Double = NaN

Это означает, что у меня должно быть два NanAwareOrdering в зависимости от того, хочу ли я минимум или максимум, что запретило бы иметьimplicit val, Поэтому мой вопрос: как я могу определить порядок таким образом, чтобы обрабатывать оба случая одновременно?

Обновить:

Ради полноты: в ходе анализа проблемы я понял, что посылка «вырождается в проверку на NaN» на самом деле неверна. На самом деле, я думаю, что это еще страшнее

scala> List(1.0, Double.NaN).min
res1: Double = NaN

scala> List(Double.NaN, 1.0).min
res2: Double = 1.0

Ответы на вопрос(4)

Ваш ответ на вопрос