Haskell中的floor和truncate之间是否存在差异?

Tom*_*nck 11 haskell

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)


Yan*_*ier 7

这不是特定于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()走向负无穷大.


raa*_*m86 5

查看源代码,差异很快就出现了:

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)