2011-05-04 22 views
87

¿Cuál es exactamente la diferencia entre mod y rem en Haskell?Diferencia entre `mod` y` rem` en Haskell

Ambos parece 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 
+2

No conozco Haskell, pero es probable que se trate de la misma operación. 'mod'ulus ==' rem'ainder. –

+0

Para ser justos, no era la misma pregunta. La otra pregunta asumió la comprensión de la respuesta a esta pregunta. –

+0

@Dan Leyendo esa pregunta, debido a otra pregunta que tenía (http://stackoverflow.com/questions/5892188/problems-obtaining-the-list-of-divisors-of-a-number-in-haskell), I se dio cuenta de lo mismo:/ –

Respuesta

123

No son lo mismo cuando el segundo argumento es negativo:

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

Tuve la misma pregunta sobre 'rem' y' mod' en Clojure, y esta fue la respuesta. – noahlz

+9

Tampoco son lo mismo cuando el primer argumento es negativo. Consulte http://stackoverflow.com/a/8111203/1535283 y http://stackoverflow.com/a/339823/1535283 para obtener más información acerca de estas operaciones complicadas. –

+4

También desde http: // stackoverflow.com/a/6964760/205521 parece que 'rem' es el más rápido. –

34

Sí, esas funciones actúan de forma diferente. Como se define en la official documentation:

quot se división entera trunca hacia cero

rem es resto entero, satisfactoria:

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

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

mod es número entero módulo, que satisface:

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

Puede realmente se nota la diferencia cuando se utiliza 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 

 

+0

Tus últimos cuatro ejemplos probablemente no sean lo que quieres decir, ya que 'mod' y' rem' se asocian más que '(-)'. He editado tu comentario, ya que parece que no puedo poner líneas múltiples en este comentario. –

+1

@ErikHesselink: introdujo un error con su edición. '(-5) \' mod \ '3 == 1' –

+0

@ChengSun Gracias, lo he solucionado. Debería ser en vivo después de la revisión. –

8

En términos prácticos:

Si sabe tanto los operandos son positivos, generalmente debe usar quot, rem o quotRem para mayor eficiencia.

Si no sabe que ambos operandos son positivos, debe pensar en cómo quiere que sean los resultados. Probablemente no desee quotRem, pero es posible que tampoco desee divMod. La ley (x `div` y)*y + (x `mod` y) == x 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 que 0 <= x `mod` y < y (división euclidiana).

0

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

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