2008-12-04 55 views
35

從Haskell的報告:quotRem和divMod之間的區別是什麼時候有用?

的QUOT,REM,DIV,以及mod類 方法滿足這些法律如果y是 非零:

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

quot是整數除法截斷 朝向零,而div 的結果被截斷爲負無窮。

例如:

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

什麼是其中一些例子的結果如何被截斷的問題有什麼區別?

回答

35

許多語言都有一個「mod」或「%」運算符,該運算符將除法後的剩餘部分截斷爲0;例如C,C++和Java,大概C#,會說:

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

Haskell的quotrem旨在模仿這種行爲。我可以想象在一些人爲設想的情況下,與某些C程序的輸出的兼容性可能是可取的。

Haskell的divmod,隨後Python的/和%,跟隨數學家(至少數理論家)的約定,始終截斷師(不計入0 - 接近負無窮大),從而使其餘的是總是非負的。因此,在Python中,

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

Haskell的divmod這樣的行爲。

+5

「這樣餘數總是非負的」從技術上講,mod的符號遵循第二個操作數的符號。 – newacct 2009-05-07 04:41:00

+0

嗯,你說得對。我不明白這個設計決定... – ShreevatsaR 2009-05-07 15:31:01

6

一個簡單的例子,重要的是測試一個整數是偶數還是奇數。

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 

注意,當然,你可能會避免只定義奇以這種方式思考這些問題:

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

一般來說,只要記住,對於y > 0x mod y總有返回>= 0x rem y返回0或與x相同的符號。

23

這不完全是您的問題的答案,但是在x86上的GHC上,quotRem on Int會編譯爲單個機器指令,而divMod會做很多工作。因此,如果您處於速度臨界區域並且僅使用正數,則quotRem是要走的路。

相關問題