Różnica między „mod” i „rem” w Haskell

130

Jaka jest dokładnie różnica między modiw remHaskell?

Wydaje się, że oba dają te same wyniki

*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
źródło
3
Nie znam Haskella, ale prawdopodobnie to ta sama operacja. ulus mod== remainder.
Matthew Scharley
Szczerze mówiąc, to nie było to samo pytanie. Drugie pytanie zakładało zrozumienie odpowiedzi na to pytanie.
Dan Burton
@Dan Czytając to pytanie, z powodu innego pytania, które miałem ( stackoverflow.com/questions/5892188/… ), zdałem sobie sprawę, że to samo: /
Oscar Mederos
2
jest taka sama jak między divaquot
newacct

Odpowiedzi:

181

Nie są takie same, gdy drugi argument jest ujemny:

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2
Fred Foo
źródło
20
Miałem to samo pytanie dotyczące remi modw Clojure i to była odpowiedź.
noahlz
11
Nie są też takie same, gdy pierwszy argument jest negatywny. Więcej informacji na temat tych trudnych operacji można znaleźć na stackoverflow.com/a/8111203/1535283 i stackoverflow.com/a/339823/1535283 .
Scott Olson,
4
Również ze stackoverflow.com/a/6964760/205521 wydaje się, że remjest najszybszy.
Thomas Ahle,
16
Chociaż ta odpowiedź jest poprawna, odpowiedź, która mówi tylko „nie to samo” na pytanie „jaka jest różnica”, jest bardzo zła. Byłbym mile widziany, gdybyś mógł rozwinąć „jak” są one różne i prawdopodobnie niektóre przypadki użycia.
poitroae
59

Tak, te funkcje działają inaczej. Jak określono w oficjalnej dokumentacji :

quot jest dzieleniem całkowitoliczbowym obciętym do zera

rem jest resztą całkowitą, spełniającą:

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

div jest dzieleniem całkowitoliczbowym obciętym w kierunku ujemnej nieskończoności

mod jest modułem całkowitym, spełniającym:

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

Naprawdę możesz zauważyć różnicę, gdy użyjesz liczby ujemnej jako drugiego parametru, a wynik nie będzie zerowy:

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
źródło
Twoje ostatnie cztery przykłady nie są prawdopodobnie co masz na myśli, bo modi remkojarzy się silniej niż (-). Zmodyfikowałem Twój komentarz, ponieważ nie mogę umieścić w nim treści wielowierszowych.
Erik Hesselink
1
@ErikHesselink: wprowadziłeś błąd w swojej edycji. (-5) `mod` 3 == 1
Cheng Sun
@ChengSun Dzięki, naprawiłem to. Powinien być aktywny po sprawdzeniu.
Erik Hesselink
16

Praktycznie rzecz biorąc:

Jeśli znasz oba operandy są pozytywne, należy zazwyczaj użyć quot, remlub quotRemefektywności.

Jeśli nie wiesz, że oba operandy są pozytywne, musisz pomyśleć o tym, jak chcesz, aby wyglądały wyniki. Prawdopodobnie nie chcesz quotRem, ale możesz też nie chcieć divMod. (x `div` y)*y + (x `mod` y) == xPrawo jest bardzo dobry, ale zaokrąglenie podział ku negatywnej nieskończoności (styl podziału Knuth) jest często mniej przydatne i mniej wydajny niż zapewnienie, że 0 <= x `mod` y < y(euklidesowej podział).

dfeuer
źródło
5

Jeśli chcesz przetestować tylko podzielność, zawsze powinieneś używać rem.

Zasadniczo x `mod` y == 0jest odpowiednikiem x `rem` y == 0, ale remjest szybszy niż mod.

sjakobi
źródło