haskell中’mod’和’rem’的区别

Difference between `mod` and `rem` in Haskell

haskell的modrem到底有什么区别?

两个结果似乎都一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*Main> mod 2 3
2
*Main> rem 2 3
2
*Main> mod 10 5
0
*Main> rem 10 5
0
*Main> mod 1 0
*** Exception: divide by zero
*Main> rem 1 0
*** Exception: divide by zero
*Main> mod 1 (-1)
0
*Main> rem 1 (-1)
0


当第二个论点是否定的时候,它们就不一样了:

1
2
2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2


是的,这些功能的作用是不同的。如官方文件所定义:

quot是整数除法,截断为零。

rem为整数余数,满足:

1
(x `quot` y)*y + (x `rem` y) == x

div是整数除法,被截断为负无穷大。

mod为整数模,满足:

1
(x `div` y)*y + (x `mod` y) == x

当使用负数作为第二个参数且结果不是零时,您可以真正注意到差异:

1
2
3
4
5
6
7
8
9
10
11
5 `mod` 3 == 2
5 `rem` 3 == 2

5 `mod` (-3) == -1
5 `rem` (-3) == 2

(-5) `mod` 3 == 1
(-5) `rem` 3 == -2

(-5) `mod` (-3) == -2
(-5) `rem` (-3) == -2

nbsp;


实际上:

如果你知道两个操作数都是正的,你通常应该使用quotremquotRem来提高效率。

如果你不知道两个操作数都是正的,你必须考虑一下你想要的结果是什么样子的。你可能不想要quotRem,但也可能不想要divMod(x `div` y)*y + (x `mod` y) == x定律是一个很好的定律,但是向负无穷(knuth样式的除法)的四舍五入除法通常不如确保0 <= x `mod` y < y除法(欧几里得除法)有用且效率低。


如果您只想测试可分割性,那么应该始终使用rem

本质上,x `mod` y == 0相当于x `rem` y == 0,但remmod快。