Quand la différence entre quotRem et divMod est-elle utile?
Depuis le haskell rapport:
les classes quot, rem, div Et mod les méthodes satisfont à ces lois si y est non-zéro:
(x `quot` y)*y + (x `rem` y) == x (x `div` y)*y + (x `mod` y) == x
<!-La division entière est tronquée à zéro, alors que le résultat de
div
est tronqué vers l'infini négatif.
Par exemple:
Prelude> (-12) `quot` 5
-2
Prelude> (-12) `div` 5
-3
Quels sont quelques exemples où la différence entre la façon dont le résultat est tronqué questions?
3 réponses
beaucoup de langues ont un opérateur "mod" ou " % " qui donne le reste après division avec une troncature vers 0; par exemple C, C++, et Java, et probablement C#, dirait:
(-11)/5 = -2
(-11)%5 = -1
5*((-11)/5) + (-11)%5 = 5*(-2) + (-1) = -11.
Haskell quot
et rem
visent à imiter ce comportement. Je peux imaginer que la compatibilité avec la sortie d'un programme C pourrait être souhaitable dans une situation artificielle.
Haskell div
et mod
, et par la suite Python's / et%, suivent la convention de les mathématiciens (au moins nombre-théoriciens) toujours tronquer bas division (pas vers 0 -- vers l'infini négatif) de sorte que le reste est toujours non négatif. Ainsi, en Python,
(-11)/5 = -3
(-11)%5 = 4
5*((-11)/5) + (-11)%5 = 5*(-3) + 4 = -11.
Haskell div
et mod
suivez ce comportement.
ce n'est pas exactement une réponse à votre question, mais dans GHC sur x86, quotRem sur Int compilera jusqu'à une seule instruction machine, alors que divMod fait un peu plus de travail. Donc, si vous êtes dans une section de vitesse critique et que vous travaillez sur des nombres positifs seulement, quotRem est la voie à suivre.
Un exemple simple où il serait question est de tester si un entier est pair ou impair.
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
notez, bien sûr, que vous pourriez éviter de penser à ces questions en définissant simplement odd de cette façon:
let odd x = x `rem` 2 /= 0
odd 1 // True
odd (-1) // True
en général, il suffit de se rappeler que, pour y > 0
, x mod y
toujours retourner quelque chose >= 0
x rem y
renvoie 0 ou quelque chose du même signe que X.