关于haskell:quotRem和divMod之间的区别何时有用?

When is the difference between quotRem and divMod useful?

从Haskell报告:

The quot, rem, div, and mod class
methods satisfy these laws if y is
non-zero:

1
2
(x `quot` y)*y + (x `rem` y) == x
(x `div`  y)*y + (x `mod` y) == x

quot is integer division truncated
toward zero, while the result of div
is truncated toward negative infinity.

例如:

1
2
3
4
Prelude> (-12) `quot` 5
-2
Prelude> (-12) `div` 5
-3

有什么例子可以说明截断结果的不同之处?


许多语言都有一个"mod"或"%"运算符,它用截断后的0来给出余数,例如C、C++和Java,很可能是C。

1
2
3
(-11)/5 = -2
(-11)%5 = -1
5*((-11)/5) + (-11)%5 = 5*(-2) + (-1) = -11.

Haskell的quotrem意在模仿这种行为。我可以想象,在某些人为的情况下,与某些C程序的输出兼容可能是可取的。

haskell的divmod,随后是python的/和%,遵循数学家(至少是数理论家)的惯例,总是截断除法(不是朝0——朝负无穷大),使余数总是非负的。因此在python中,

1
2
3
(-11)/5 = -3
(-11)%5 = 4
5*((-11)/5) + (-11)%5 = 5*(-3) + 4 = -11.

haskell的divmod遵循这种行为。


这不完全是您问题的答案,但是在x86上的ghc中,int上的Quoterm将编译成一条机器指令,而divmod则要做更多的工作。所以如果你在一个速度临界区,只研究正数,Quoterm就是你要做的。


一个简单的例子是测试一个整数是偶数还是奇数。

1
2
3
4
5
6
7
let buggyOdd x = x `rem` 2 == 1
buggyOdd 1 // True
buggyOdd (-1) // False (wrong!)

let odd x = x `mod` 2 == 1
odd 1 // True
odd (-1) // True

当然,请注意,您可以通过以下方式定义奇数来避免思考这些问题:

1
2
3
let odd x = x `rem` 2 /= 0
odd 1 // True
odd (-1) // True

一般来说,只要记住,对于y > 0x mod y总是返回>= 0的某个值,而x rem y返回0或与x符号相同的某个值。