我有一个415920个数字的mins
列表,全部应该关闭到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
答案 0 :(得分:14)
所有问题的原因是该列表包含NaN
。显然它违反了Ord
的总排序要求[*],所以你不能指望使用排序的算法 - 选择最小值或排序 - 在输入中产生正确的结果。相反,他们会产生一些取决于其内部实现的东西,并且可能根据看似不重要的原因(例如输入顺序)而有所不同。你应该在做其他任何事情之前将其过滤掉。
[*] Ord
没有明确写出法律(NaN也会破坏Eq
),但这里是破坏整体规则的例子,因为它是described in Wikipedia(感谢@sjakobi纠正):
Prelude> let nan = 0 / 0
Prelude> nan
NaN
Prelude> nan <= 1
False
Prelude> 1 <= nan
False
Prelude>