Clojure 中 mod 和 rem 的区别

问题描述 投票:0回答:4

我无法理解这两个 (

mod
&
rem
) 函数之间的区别。

clojure clojurescript
4个回答
24
投票

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
函数被定义为使得
(mod a b)
对于正 b 的结果始终在 [0,b-1] 范围内,即使 a 为负。这通常是您对“模算术”的期望;无论您朝哪个方向走,都会永远重复相同的数字。

它与整数除法运算结合使用特别有用,整数除法运算向下舍入而不是向零舍入(也就是说,如果答案是否定的,四舍五入的答案更负),不幸的是,Clojure 没有预定义函数。不过,您可以定义自己的:

(defn div [a b] (int (. Math floor (/ a b))))

那么

(div -3 2)
就是-2,因为-2 * 2 = -4是小于等于-3的2的最大偶数倍。 (同样,-2 是小于或等于-1.5 的最大整数。)

事实上,这就是许多其他语言中整数除法的定义方式,例如 Common Lisp(双参数

floor
函数)、Python(
//
运算符)、Ruby(
Integer#div
方法)等。

定义了这样的函数后,上述对

quot
/
rem
的断言也适用于
div
/
mod
:

(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。


0
投票

数学表示:

rem (a, b) = a - (quot (a, b) * b)
mod (a, b) = a - (floor (a / b) * b)

用实际例子来说明差异:

;; Using rem
(rem 7 3)    ; => 1
(rem -7 3)   ; => -1
(rem 7 -3)   ; => 1
(rem -7 -3)  ; => -1

;; Using mod
(mod 7 3)    ; => 1
(mod -7 3)   ; => 2
(mod 7 -3)   ; => -2
(mod -7 -3)  ; => -2
© www.soinside.com 2019 - 2024. All rights reserved.