Diferencia entre `mod` y` rem` en Haskell

130

¿Cuál es exactamente la diferencia entre mody remen Haskell?

Ambos parecen dar los mismos resultados.

*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
fuente
3
No conozco a Haskell, pero es probable que se trate de la misma operación. modulus == remainder.
Matthew Scharley
Para ser justos, no era la misma pregunta. La otra pregunta asumió la comprensión de la respuesta a esta pregunta.
Dan Burton,
@Dan Leyendo esa pregunta, debido a otra pregunta que tuve ( stackoverflow.com/questions/5892188/… ), me di cuenta de lo mismo: /
Oscar Mederos
2
es la misma diferencia entre divyquot
newacct

Respuestas:

181

No son lo mismo cuando el segundo argumento es negativo:

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2
Fred Foo
fuente
20
Tenía la misma pregunta sobre remy moden Clojure, y esta fue la respuesta.
noahlz
11
Tampoco son iguales cuando el primer argumento es negativo. Consulte stackoverflow.com/a/8111203/1535283 y stackoverflow.com/a/339823/1535283 para obtener más información sobre estas operaciones difíciles.
Scott Olson
44
También desde stackoverflow.com/a/6964760/205521 parece que remes el más rápido.
Thomas Ahle
16
Aunque esta respuesta es correcta, una respuesta que dice no más que "no es lo mismo" a una pregunta "cuál es la diferencia" es muy mala. Le agradecería si pudiera ampliar "cómo" son diferentes y algunos casos de uso probablemente.
poitroae
59

Sí, esas funciones actúan de manera diferente. Como se define en la documentación oficial :

quot es la división entera truncada hacia cero

rem es el resto entero, satisfactorio:

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

div es la división entera truncada hacia el infinito negativo

mod es un módulo entero que satisface:

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

Realmente puedes notar la diferencia cuando usas un número negativo como segundo parámetro y el resultado no es cero:

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
fuente
Sus últimos cuatro ejemplos no son, probablemente, lo que quiere decir, desde mody remasociado con más fuerza que (-). He editado tu comentario ya que parece que no puedo poner cosas de varias líneas en este comentario.
Erik Hesselink
1
@ErikHesselink: introdujo un error con su edición. (-5) `mod` 3 == 1
Cheng Sun
@ChengSun Gracias, lo arreglé. Debería estar en vivo después de la revisión.
Erik Hesselink
16

Hablando practicamente:

Si conoces a los dos operandos son positivos, por lo general debe utilizar quot, remo quotRempara mayor eficiencia.

Si no sabe que ambos operandos son positivos, debe pensar en cómo desea que se vean los resultados. Probablemente no quieras quotRem, pero quizás tampoco quieras divMod. La (x `div` y)*y + (x `mod` y) == xley es muy buena, pero redondear la división hacia el infinito negativo (división de estilo Knuth) a menudo es menos útil y menos eficiente que asegurar eso 0 <= x `mod` y < y(división euclidiana).

dfeuer
fuente
5

En caso de que solo desee probar la divisibilidad, siempre debe usar rem.

Esencialmente x `mod` y == 0es equivalente a x `rem` y == 0, pero remes más rápido que mod.

sjakobi
fuente