Differenza tra `mod` e` rem` in Haskell


130

Qual è esattamente la differenza tra mode remin Haskell?

Entrambi sembrano dare gli stessi risultati

*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

3
Non conosco Haskell, ma è probabile che si tratti della stessa operazione. modulus == remainder.
Matthew Scharley,

Ad essere sinceri, non era la stessa domanda. L'altra domanda ha assunto la comprensione della risposta a questa domanda.
Dan Burton,

@Dan Leggendo quella domanda, a causa di un'altra domanda che avevo ( stackoverflow.com/questions/5892188/… ), mi sono reso conto lo stesso: /
Oscar Mederos

2
è la stessa differenza tra divequot
newacct

Risposte:


181

Non sono gli stessi quando il secondo argomento è negativo:

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

20
Avevo la stessa domanda su reme modin Clojure, e questa era la risposta.
Noahlz,

11
Né sono uguali quando il primo argomento è negativo. Vedi stackoverflow.com/a/8111203/1535283 e stackoverflow.com/a/339823/1535283 per qualche informazione in più su queste complicate operazioni.
Scott Olson,

4
Anche da stackoverflow.com/a/6964760/205521 sembra che remsia il più veloce.
Thomas Ahle,

16
Sebbene questa risposta sia corretta, una risposta che afferma non più di "non la stessa" a una domanda "qual è la differenza" è molto negativa. Mi farebbe piacere se tu potessi ampliare il "come" siano diversi e alcuni casi d'uso probabilmente.
poitroae,

59

Sì, queste funzioni agiscono diversamente. Come definito nella documentazione ufficiale :

quot è la divisione intera troncata verso zero

rem è resto intero, soddisfacente:

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

div è la divisione intera troncata verso l'infinito negativo

mod è un modulo intero, soddisfacente:

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

Puoi davvero notare la differenza quando usi un numero negativo come secondo parametro e il risultato non è zero:

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

 


I tuoi ultimi quattro esempi probabilmente non sono ciò che intendi, dal momento modche sono remassociati più fortemente di (-). Ho modificato il tuo commento poiché non riesco a inserire elementi a più righe in questo commento.
Erik Hesselink,

1
@ErikHesselink: hai introdotto un errore con la tua modifica. (-5) `mod` 3 == 1
Cheng dom

@ChengSun Grazie, l'ho risolto. Dovrebbe essere attivo dopo la revisione.
Erik Hesselink,

16

In pratica:

Se si conosce entrambi gli operandi sono positivi, di solito si dovrebbe usare quot, remo quotRemper l'efficienza.

Se non sai che entrambi gli operandi sono positivi, devi pensare a come vuoi che appaiano i risultati. Probabilmente non vuoi quotRem, ma potresti non volerlo divModneanche. La (x `div` y)*y + (x `mod` y) == xlegge è molto buona, ma arrotondare la divisione verso l'infinito negativo (divisione in stile Knuth) è spesso meno utile e meno efficiente che assicurarla 0 <= x `mod` y < y(divisione euclidea).


5

Nel caso in cui si desideri solo verificare la divisibilità, è necessario utilizzare sempre rem.

Essenzialmente x `mod` y == 0è equivalente a x `rem` y == 0, ma remè più veloce di mod.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.