Есть ли ошибка в минимальной функции?
У меня есть список mins
415920 номеров, все должны быть закрыты до 0.1
:
Prelude Lib> take 5 mins
[9.83610706554002e-2,9.847021825032128e-2,9.847021825032128e-2,9.898395035483082e-2,9.898395035483082e-2]
Тем не мение:
Prelude Lib> minimum mins
0.10087849151477328
minimum
функция не должна возвращать минимум?
Этот результат звучит правдоподобно:
Prelude Lib> foldr min 100000 mins
1.1763616593045858e-4
Это ошибка, или я неправильно понимаю minimum
?
Аналогичная проблема с maximum
:
Prelude Lib> maximum mins
3261145.0627630088
Prelude Lib> foldr max 0 mins
0.1207868227600914
Сортировка списка дает третий результат для максимума:
Prelude Lib> import Data.List as L
Prelude Lib L> mins' = sort mins
Prelude Lib L> head mins'
1.1763616593045858e-4
Prelude Lib L> last mins'
0.10295664278431726
И применение minimum
и maximum
в отсортированном списке дает третий результат для минимума:
Prelude Lib L> minimum mins'
0.10045801977483232
Prelude Lib L> maximum mins'
3261145.0627630088
редактировать
После комментария @max630 я искал в списке текстовый редактор. 3261145.0627630088
действительно здесь, и есть некоторые NaN
:
NaN,NaN,3261145.0627630088
Вывод: похоже, что minimum
дает неправильный результат, а maximum
дает правильный результат.
foldr max
дает неверный результат, foldl max
дает хороший результат:
> foldl max 0 mins
3261145.0627630088
Ответы
Ответ 1
Причина всех проблем в том, что список содержит NaN
. По-видимому, это нарушало требование общего заказа Ord
[*], поэтому вы не можете ожидать, что алгоритмы, которые используют порядок - либо минимальный выбор, либо сортировку - для получения правильного результата, когда он находится на входе. Вместо этого они будут производить что-то, что зависит от их внутренней реализации, и могут быть разными в зависимости от кажущихся несущественными причин, например, порядка ввода. Вы должны отфильтровать его, прежде чем делать что-либо еще.
[*] У Ord
нет законов, написанных явно (ни Eq
которые NaN также не разрывает), а вот пример нарушения правила тотальности, как описано в Википедии (спасибо @sjakobi для исправления):
Prelude> let nan = 0 / 0
Prelude> nan
NaN
Prelude> nan <= 1
False
Prelude> 1 <= nan
False
Prelude>