Haskell 之间floor
和之间的功能是否存在差异truncate
?
它们似乎执行相同的功能,并且它们具有相同的类型签名:
truncate :: (Integral b, RealFrac a) => a -> b
floor :: (Integral b, RealFrac a) => a -> b
Wil*_*sem 20
是的,对于负数.如果我们阅读文档,我们会看到:
truncate :: Integral b => a -> b
truncate x
返回最接近x
零和的整数x
和:
floor :: Integral b => a -> b
floor x
返回不大于的最大整数x
所以如果我们输入一个负数,就像-3.5
我们得到的那样:
Prelude> truncate (-3.5)
-3
Prelude> floor (-3.5)
-4
Run Code Online (Sandbox Code Playgroud)
这不是特定于haskell,但这些功能之间存在差异.Floor表示不高于给定数字的最高整数.截断意味着在某种程度上移除,在这种情况下是小数部分.那些对零和正数具有相同的效果,但不是负数.
这是Python的快速比较:
>>> for i in range(-5,6):
... j=0.5*i
... print(j,floor(j),ceil(j),trunc(j),round(j))
...
-2.5 -3 -2 -2 -2
-2.0 -2 -2 -2 -2
-1.5 -2 -1 -1 -2
-1.0 -1 -1 -1 -1
-0.5 -1 0 0 0
0.0 0 0 0 0
0.5 0 1 0 0
1.0 1 1 1 1
1.5 1 2 1 2
2.0 2 2 2 2
2.5 2 3 2 2
Run Code Online (Sandbox Code Playgroud)
从本质上讲,trunc()向零和floor()走向负无穷大.
查看源代码,差异很快就出现了:
truncate x = m where (m,_) = properFraction x
Run Code Online (Sandbox Code Playgroud)
和
floor x = if r < 0 then n - 1 else n
where (n,r) = properFraction x
Run Code Online (Sandbox Code Playgroud)
我们看到差异只会出现在负数上,所以:
Prelude> floor (negate 2.1)
-3
Prelude> truncate (negate 2.1)
-2
Run Code Online (Sandbox Code Playgroud)