Perbedaan antara `mod` dan` rem` di Haskell

130

Apa sebenarnya perbedaan antara moddan remdi Haskell?

Keduanya sepertinya memberikan hasil yang sama

*Main> mod 2 3
2
*Main> rem 2 3
2
*Main> mod 10 5
0
*Main> rem 10 5
0
*Main> mod 1 0
*** Exception: divide by zero
*Main> rem 1 0
*** Exception: divide by zero
*Main> mod 1 (-1)
0
*Main> rem 1 (-1)
0
Oscar Mederos
sumber
3
Tidak tahu Haskell, tetapi kemungkinan ini adalah operasi yang sama. modulus == remainder.
Matthew Scharley
Agar adil, itu bukan pertanyaan yang sama. Pertanyaan lain mengasumsikan pemahaman tentang jawaban untuk pertanyaan ini.
Dan Burton
@Dan Membaca pertanyaan itu, karena pertanyaan lain yang saya miliki ( stackoverflow.com/questions/5892188/... ), saya menyadari hal yang sama: /
Oscar Mederos
2
itu perbedaan yang sama seperti antara divdanquot
newacct

Jawaban:

181

Mereka tidak sama ketika argumen kedua negatif:

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2
Fred Foo
sumber
20
Saya memiliki pertanyaan yang sama tentang remdan moddi Clojure, dan ini adalah jawabannya.
noahlz
11
Mereka juga tidak sama ketika argumen pertama negatif. Lihat stackoverflow.com/a/8111203/1535283 dan stackoverflow.com/a/339823/1535283 untuk beberapa info lebih lanjut tentang operasi rumit ini.
Scott Olson
4
Juga dari stackoverflow.com/a/6964760/205521 sepertinya remtercepat.
Thomas Ahle
16
Meskipun jawaban ini benar, jawaban yang mengklaim tidak lebih dari "tidak sama" dengan pertanyaan "apa bedanya" adalah jawaban yang sangat buruk. Saya akan menyambut jika Anda dapat memperluas "bagaimana" mereka berbeda dan beberapa usecases mungkin.
poitroae
59

Ya, fungsi-fungsi itu bertindak secara berbeda. Sebagaimana didefinisikan dalam dokumentasi resmi :

quot adalah pembagian bilangan terpotong ke arah nol

rem sisa integer, memuaskan:

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

div adalah pembagian integer yang terpotong menuju infinity negatif

mod adalah integer modulus, memuaskan:

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

Anda benar-benar dapat melihat perbedaan ketika Anda menggunakan angka negatif sebagai parameter kedua dan hasilnya bukan nol:

5 `mod` 3 == 2
5 `rem` 3 == 2

5 `mod` (-3) == -1
5 `rem` (-3) == 2

(-5) `mod` 3 == 1
(-5) `rem` 3 == -2

(-5) `mod` (-3) == -2
(-5) `rem` (-3) == -2

 

Giuseppe Bertone
sumber
Empat contoh terakhir Anda mungkin bukan yang Anda maksudkan, karena moddan remkaitkan lebih kuat daripada (-). Saya telah mengedit komentar Anda karena sepertinya saya tidak bisa memasukkan banyak hal dalam komentar ini.
Erik Hesselink
1
@ErikHesselink: Anda membuat kesalahan dengan hasil edit Anda. (-5) `mod` 3 == 1
Cheng Sun
@ChengSun Terima kasih, saya sudah memperbaikinya. Harus ditayangkan setelah ditinjau.
Erik Hesselink
16

Secara praktis berbicara:

Jika Anda tahu kedua operan positif, Anda harus biasanya menggunakan quot, rematauquotRem untuk efisiensi.

Jika Anda tidak tahu kedua operan itu positif, Anda harus memikirkan seperti apa hasil yang Anda inginkan. Anda mungkin tidak mau quotRem, tetapi Anda mungkin juga tidak mau divMod. The (x `div` y)*y + (x `mod` y) == xhukum adalah salah satu yang sangat baik, tetapi pembulatan divisi menuju tak terhingga negatif (divisi gaya Knuth) sering kurang berguna dan kurang efisien daripada memastikan bahwa 0 <= x `mod` y < y(divisi Euclidean).

dfeuer
sumber
5

Jika Anda hanya ingin menguji apakah dapat dibagi, Anda harus selalu menggunakannya rem.

Pada dasarnya x `mod` y == 0setara dengan x `rem` y == 0, tetapi remlebih cepat dari mod.

sjakobi
sumber