haskell - ¿Cuándo es útil la diferencia entre quotRem y divMod?
mod haskell (3)
Esta no es exactamente una respuesta a su pregunta, pero en GHC en x86, quotRem on Int se compilará en una sola instrucción de máquina, mientras que divMod hace bastante más trabajo. Entonces, si se encuentra en una sección de velocidad crítica y solo trabaja con números positivos, quimio es el camino a seguir.
Del informe de Haskell:
Los métodos quot, rem, div y mod class satisfacen estas leyes si y no es cero:
(x `quot` y)*y + (x `rem` y) == x (x `div` y)*y + (x `mod` y) == x
quot
es la división entera truncada hacia cero, mientras que el resultado dediv
se trunca hacia el infinito negativo.
Por ejemplo:
Prelude> (-12) `quot` 5
-2
Prelude> (-12) `div` 5
-3
¿Cuáles son algunos ejemplos de dónde importa la diferencia entre cómo se trunca el resultado?
Muchos idiomas tienen un operador "mod" o "%" que da el resto después de la división con truncamiento hacia 0; por ejemplo, C, C ++ y Java, y probablemente C #, dirían:
(-11)/5 = -2
(-11)%5 = -1
5*((-11)/5) + (-11)%5 = 5*(-2) + (-1) = -11.
Los quot
y rem
Haskell están destinados a imitar este comportamiento. Me imagino que la compatibilidad con la producción de algún programa de C podría ser deseable en alguna situación artificial.
El div
y mod
Haskell, y posteriormente Python / y%, siguen la convención de los matemáticos (al menos teóricos numéricos) al truncar siempre la división (no hacia 0 - hacia el infinito negativo) para que el resto siempre sea no negativo. Así en Python,
(-11)/5 = -3
(-11)%5 = 4
5*((-11)/5) + (-11)%5 = 5*(-3) + 4 = -11.
El div
y mod
Haskell siguen este comportamiento.
Un ejemplo simple en el que importaría es probar si un entero es par o impar.
let buggyOdd x = x `rem` 2 == 1
buggyOdd 1 // True
buggyOdd (-1) // False (wrong!)
let odd x = x `mod` 2 == 1
odd 1 // True
odd (-1) // True
Tenga en cuenta, por supuesto, que podría evitar pensar en estos problemas simplemente definiendo impar de esta manera:
let odd x = x `rem` 2 /= 0
odd 1 // True
odd (-1) // True
En general, solo recuerde que, para y > 0
, x mod y
siempre devuelve algo >= 0
mientras que x rem y
devuelve 0 o algo del mismo signo que x.