Unterschied zwischen "mod" und "rem" in Haskell

130

Was genau ist der Unterschied zwischen modund remin Haskell?

Beide scheinen die gleichen Ergebnisse zu liefern

*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
quelle
3
Ich kenne Haskell nicht, aber es ist wahrscheinlich, dass es sich um dieselbe Operation handelt. modulus == remainder.
Matthew Scharley
Um fair zu sein, war es nicht die gleiche Frage. Die andere Frage setzte das Verständnis der Antwort auf diese Frage voraus.
Dan Burton
@Dan Als ich diese Frage las , wurde mir aufgrund einer anderen Frage ( stackoverflow.com/questions/5892188/… ) dasselbe klar: /
Oscar Mederos
2
Es ist der gleiche Unterschied wie zwischen divundquot
Newacct

Antworten:

181

Sie sind nicht gleich, wenn das zweite Argument negativ ist:

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2
Fred Foo
quelle
20
Ich hatte die gleiche Frage zu remund modin Clojure, und das war die Antwort.
Noahlz
11
Sie sind auch nicht gleich, wenn das erste Argument negativ ist. Weitere Informationen zu diesen kniffligen Vorgängen finden Sie unter stackoverflow.com/a/8111203/1535283 und stackoverflow.com/a/339823/1535283 .
Scott Olson
4
Auch von stackoverflow.com/a/6964760/205521 scheint remes am schnellsten zu sein.
Thomas Ahle
16
Obwohl diese Antwort richtig ist, ist eine Antwort, die nicht mehr als "nicht dasselbe" auf eine Frage "Was ist der Unterschied" behauptet, sehr schlecht. Ich würde es begrüßen, wenn Sie erläutern könnten, "wie" sie unterschiedlich sind und einige Anwendungsfälle wahrscheinlich.
Poitroae
59

Ja, diese Funktionen verhalten sich anders. Wie in der offiziellen Dokumentation definiert :

quot ist eine ganzzahlige Division, die gegen Null abgeschnitten ist

rem ist ganzzahliger Rest, befriedigend:

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

div ist eine ganzzahlige Division, die in Richtung negativer Unendlichkeit abgeschnitten ist

mod ist ein ganzzahliger Modul, der erfüllt:

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

Sie können den Unterschied wirklich bemerken, wenn Sie eine negative Zahl als zweiten Parameter verwenden und das Ergebnis nicht Null ist:

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
quelle
Ihre letzten vier Beispiele sind wahrscheinlich nicht das, was Sie meinen, da modund remassoziieren stärker als (-). Ich habe Ihren Kommentar bearbeitet, da ich diesen Kommentar nicht mehrzeilig einfügen kann.
Erik Hesselink
1
@ErikHesselink: Sie haben bei Ihrer Bearbeitung einen Fehler festgestellt. (-5) `mod` 3 == 1
Cheng Sun
@ChengSun Danke, ich habe es behoben. Sollte nach Überprüfung live sein.
Erik Hesselink
16

Praktisch gesprochen:

Wenn Sie wissen beide Operanden positiv sind, sollten Sie in der Regel verwenden quot, remoderquotRem für Effizienz.

Wenn Sie nicht wissen, dass beide Operanden positiv sind, müssen Sie sich überlegen, wie die Ergebnisse aussehen sollen. Sie wollen wahrscheinlich nicht quotRem, aber Sie wollen vielleicht auch nicht divMod. Das (x `div` y)*y + (x `mod` y) == xGesetz ist sehr gut, aber eine Rundung auf negative Unendlichkeit (Knuth-Stil-Teilung) ist oft weniger nützlich und weniger effizient als dies sicherzustellen 0 <= x `mod` y < y(euklidische Teilung).

dfeuer
quelle
5

Wenn Sie nur die Teilbarkeit testen möchten, sollten Sie immer verwenden rem.

Im Wesentlichen x `mod` y == 0entspricht, x `rem` y == 0ist aber remschneller als mod.

sjakobi
quelle