Haskell中`mod`和`rem`之间的区别
Posted
技术标签:
【中文标题】Haskell中`mod`和`rem`之间的区别【英文标题】:Difference between `mod` and `rem` in Haskell 【发布时间】:2011-08-18 23:13:42 【问题描述】:Haskell 中 mod
和 rem
之间到底有什么区别?
两者似乎给出相同的结果
*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
【问题讨论】:
不知道 Haskell,但很可能这些是相同的操作。mod
ulus == rem
ainder.
公平地说,这不是同一个问题。另一个问题假设理解这个问题的答案。
@Dan 读到那个问题,因为我有另一个问题 (***.com/questions/5892188/…),我意识到了同样的情况:/
这和div
和quot
之间的区别是一样的
【参考方案1】:
当第二个参数为负时,它们不一样:
2 `mod` (-3) == -1
2 `rem` (-3) == 2
【讨论】:
我对 Clojure 中的rem
和 mod
有同样的问题,这就是答案。
当第一个参数为负时,它们也不相同。有关这些棘手操作的更多信息,请参阅 ***.com/a/8111203/1535283 和 ***.com/a/339823/1535283。
从***.com/a/6964760/205521 看来rem
是最快的。
虽然这个答案是正确的,但对于“有什么区别”的问题声称不超过“不一样”的答案是一个非常糟糕的答案。如果您可以扩展它们的“不同之处”以及可能的一些用例,我会欢迎它。【参考方案2】:
是的,这些功能的作用不同。如official documentation中所定义:
quot
是向零截断的整数除法
rem
是整数余数,满足:
(x `quot` y)*y + (x `rem` y) == x
div
是向负无穷方向截断的整数除法
mod
是整数模,满足:
(x `div` y)*y + (x `mod` y) == x
当您使用负数作为第二个参数并且结果不为零时,您可以真正注意到差异:
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
【讨论】:
您的最后四个示例可能不是您的意思,因为mod
和rem
比(-)
关联更紧密。我已编辑您的评论,因为我似乎无法在此评论中添加多行内容。
@ErikHesselink:您在编辑时引入了错误。 (-5) `mod` 3 == 1
@ChengSun 谢谢,我已经修好了。审核后应该会上线。【参考方案3】:
实际上:
如果您知道两个操作数都是正数,则通常应该使用quot
、rem
或quotRem
以提高效率。
如果您不知道两个操作数都是正数,则必须考虑您希望结果的样子。你可能不想要quotRem
,但你也可能不想要divMod
。 (x `div` y)*y + (x `mod` y) == x
定律是一个非常好的定律,但向负无穷大舍入除法(Knuth 式除法)通常不如确保 0 <= x `mod` y < y
(欧几里得除法)有用且效率低。
【讨论】:
【参考方案4】:如果您只想测试可分性,则应始终使用rem
。
基本上x `mod` y == 0
等价于x `rem` y == 0
,但rem
比mod
快。
【讨论】:
为什么rem
比mod
更快?
至少在Int
和Integer
的情况下,mod
是按照rem
来实现的,但是需要一些额外的检查:hackage.haskell.org/package/ghc-prim-0.7.0/docs/src/…,hackage.haskell.org/package/integer-gmp-1.0.3.0/docs/src/…【参考方案5】:
quotRem' a b = (q, r) where
q = truncate $ (fromIntegral a / fromIntegral b :: Rational)
r = a - b * q
divMod' a b = (q, r) where
q = floor $ (fromIntegral a / fromIntegral b :: Rational)
r = a - b * q
例如:
(-3) / 2 = -1.5
(-3) `quot` 2 = truncate (-1.5) = -1
(-3) `div` 2 = floor (-1.5) = -2
(-3) `rem` 2 = -3 - 2 * (-1) = -1
(-3) `mod` 2 = -3 - 2 * (-2) = 1
3 / (-2) = -1.5
3 `quot` (-2) = truncate (-1.5) = -1
3 `div` (-2) = floor (-1.5) = -2
3 `rem` (-2) = 3 - (-2) * (-1) = 1
3 `mod` (-2) = 3 - (-2) * (-2) = -1
【讨论】:
虽然此代码可能会解决问题,including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。以上是关于Haskell中`mod`和`rem`之间的区别的主要内容,如果未能解决你的问题,请参考以下文章