【发布时间】:2016-05-13 13:12:02
【问题描述】:
我无法理解这两个 (mod & rem) 函数之间的区别。
【问题讨论】:
标签: clojure clojurescript
我无法理解这两个 (mod & rem) 函数之间的区别。
【问题讨论】:
标签: clojure clojurescript
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
【讨论】:
mod 返回第一个数字与小于第一个数字的第二个数字的最大 整数(可能为负)倍数的差:rem 只是剩下的。
例如(rem -4 3) => -1,这并不奇怪:-4 除以 3 是 -1,而 -1 “剩余”。
但是如果我们使用 mod:(mod -4 3) => 2:
因此,即使它们通常行为相似,mod 确实不返回余数,它会做一些更具体的事情。
【讨论】:
差异显示为负数。 (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。
【讨论】: