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

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

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

 


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).


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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.