我有一个mins415920号码列表,全部应该关闭0.1:
Prelude Lib> take 5 mins
[9.83610706554002e-2,9.847021825032128e-2,9.847021825032128e-2,9.898395035483082e-2,9.898395035483082e-2]
Run Code Online (Sandbox Code Playgroud)
然而:
Prelude Lib> minimum mins
0.10087849151477328
Run Code Online (Sandbox Code Playgroud)
该minimum函数不应该返回最小值?
这个结果听起来似乎有道理:
Prelude Lib> foldr min 100000 mins
1.1763616593045858e-4
Run Code Online (Sandbox Code Playgroud)
这是一个错误,还是我误解了minimum?
类似的问题maximum:
Prelude Lib> maximum mins
3261145.0627630088
Prelude Lib> foldr max 0 mins
0.1207868227600914
Run Code Online (Sandbox Code Playgroud)
对列表进行排序会产生最大值的第三个结果:
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
Run Code Online (Sandbox Code Playgroud)
并且在排序列表上应用minimum并maximum产生最小的第三个结果:
Prelude Lib L> minimum mins'
0.10045801977483232
Prelude Lib L> maximum mins'
3261145.0627630088
Run Code Online (Sandbox Code Playgroud)
在@ max630的评论之后,我用文本编辑器搜索了列表.的3261145.0627630088的确是在这里,而且有一些NaN:
NaN,NaN,3261145.0627630088
Run Code Online (Sandbox Code Playgroud)
结论:它看起来像minimum给出了错误的结果,并maximum给出了正确的结果.
foldr max给出错误的结果,foldl max给出一个好的结果:
> foldl max 0 mins
3261145.0627630088
Run Code Online (Sandbox Code Playgroud)
max*_*630 14
所有问题的原因是列表包含NaN.显然它违反了Ord总排序要求[*],所以你不能指望使用排序的算法 - 选择最小值或排序 - 在输入时产生正确的结果.相反,他们将产生取决于其内部实现的东西,并且可能根据看似不重要的原因(例如输入顺序)而不同.你应该在做其他事情之前将其过滤掉.
[*] Ord没有明确写出法律(EqNaN也没有破坏),但是这里打破整体规则的例子,如维基百科中描述的那样(感谢@sjakobi进行纠正):
Prelude> let nan = 0 / 0
Prelude> nan
NaN
Prelude> nan <= 1
False
Prelude> 1 <= nan
False
Prelude>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
219 次 |
| 最近记录: |