27 votes

Quand la différence entre quotRem et divMod est-elle utile ?

Extrait du rapport Haskell :

La classe quot, rem, div et mod satisfont à ces lois si y est non nul :

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

quot est une division entière tronquée vers zéro, alors que le résultat de div est tronquée vers l'infini négatif.

Par exemple :

Prelude> (-12) `quot` 5
-2
Prelude> (-12) `div` 5
-3

Quels sont les exemples où la différence entre la façon dont le résultat est tronqué est importante ?

28voto

ShreevatsaR Points 21219

De nombreux langages disposent d'un opérateur "mod" ou "%" qui donne le reste après division avec troncature vers 0 ; par exemple, C, C++ et Java, et probablement C#, diraient :

(-11)/5 = -2
(-11)%5 = -1
5*((-11)/5) + (-11)%5 = 5*(-2) + (-1) = -11.

Haskell quot y rem sont destinés à imiter ce comportement. Je peux imaginer que la compatibilité avec la sortie d'un programme C pourrait être souhaitable dans certaines situations inventées.

Haskell div y mod et, par la suite, / et % de Python, suivent la convention des mathématiciens (du moins des théoriciens des nombres) en tronquant toujours en bas division (pas vers 0 -- vers l'infini négatif) de sorte que le reste soit toujours non négatif. Ainsi, en Python,

(-11)/5 = -3
(-11)%5 = 4
5*((-11)/5) + (-11)%5 = 5*(-3) + 4 = -11.

Haskell div y mod suivent ce comportement.

19voto

luqui Points 26009

Ce n'est pas exactement une réponse à votre question, mais dans GHC sur x86, quotRem sur Int se compile en une seule instruction machine, alors que divMod fait un peu plus de travail. Donc, si vous êtes dans une section où la vitesse est critique et que vous ne travaillez que sur des nombres positifs, quotRem est la voie à suivre.

6voto

namin Points 8542

Un exemple simple où cela aurait de l'importance est de tester si un nombre 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 retourner toujours quelque chose >= 0 tandis que x rem y renvoie 0 ou quelque chose du même signe que x.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X