Clojure中mod和rem的区别

16
我不了解这两个函数(modrem)之间的区别。
3个回答

22
Clojuredoc的rem函数示例描述了它与其他函数的区别:
;; rem and mod are commonly used to get the remainder.
;; mod means Gaussian mod, so the result is always
;; non-negative.  Don't confuse it with ANSI C's %
;; operator, which despite being pronounced
;; 'mod' actually implements rem, i.e. -10 % 3 = -1.

user=> (mod -10 3)
2

user=> (rem -10 3)
-1

18

mod函数返回第一个数字与第二个数字最大的(可能为负数)整数倍数之间的差:

rem函数则只返回余数。

例如:(rem -4 3) => -1,这并不奇怪:-4除以3等于-1且“剩下”-1。
但是如果我们使用mod,则会出现奇怪的情况:(mod -4 3) => 2

  • -4最接近3的最大整数倍数是-6。
  • -4减去-6等于2。

因此,尽管它们通常表现得相似,但mod并不返回余数,而是执行更具体的操作。

您可能会发现这些ClojureDocs示例有帮助。


2

当处理负数时,两者的差别就会显现出来。 (rem -3 2) 的结果是-1,而 (mod -3 2) 的结果是1。

更一般地说,rem 函数的定义是为了补充 quot 函数,该函数进行整数除法并向零舍入。因此,这个关系始终成立:

(let [q (quot a b) 
      r (rem  a b)] 
  (assert (= a (+ r (* q b)))))

例如,(quot -3 2) 的结果是-1,(rem -3 2) 的结果也是-1,(+ -1 (* -1 2)) 的结果确实是-3。
相反,mod函数的定义是,对于正数b,(mod a b)的结果始终在[0,b-1]范围内,即使a为负数。这通常是您从“模算术”中所期望的;同样的数字循环重复,无论您向哪个方向前进。
它特别适用于与向下舍入而不是向零舍入的整数除法操作一起使用(即,如果答案为负,则舍入后的答案更加负),Clojure不幸没有预定义的函数。不过你可以自己定义:
(defn div [a b] (int (. Math floor (/ a b))))

然后,(div -3 2)等于-2,因为-2 * 2 = -4是小于或等于-3的最大偶数倍数。(等价地,-2是小于或等于-1.5的最大整数。)
事实上,这就是许多其他语言中定义整数除法的方式,比如Common Lisp(双参数floor函数)、Python(//运算符)、Ruby(Integer#div方法)等。
有了这样一个函数的定义,div/mod的上述断言也适用于quot/rem
(let [q (div a b) 
      r (mod a b)] 
  (assert (= a (+ r (* q b)))))

例如,(div -3 2) 的结果为-2,(mod -3 2) 的结果为1,(+ 1 (* -2 2)) 的结果再次等于-3。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接