Quelle est exactement la différence entre mod
et rem
dans Haskell?
Les deux semblent donner les mêmes résultats
*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
Ils ne sont pas les mêmes quand le deuxième argument est négatif:
2 `mod` (-3) == -1
2 `rem` (-3) == 2
Oui, ces fonctions agissent différemment. Tel que défini dans le documentation officielle :
quot
est une division entière tronquée vers zéro
rem
est un reste entier satisfaisant:
(x `quot` y)*y + (x `rem` y) == x
div
est une division entière tronquée vers l'infini négatif
mod
est un module entier satisfaisant:
(x `div` y)*y + (x `mod` y) == x
Vous pouvez vraiment remarquer la différence lorsque vous utilisez un nombre négatif en tant que second paramètre et que le résultat n'est pas nul:
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
Pratiquement parlant:
Si vous savez que les deux opérandes sont positifs, vous devez généralement utiliser quot
, rem
ou quotRem
pour plus d'efficacité.
Si vous ne savez pas que les deux opérandes sont positifs, vous devez penser à ce que vous voulez que les résultats ressemblent. Vous ne voulez probablement pas quotRem
, mais vous ne voulez peut-être pas non plus divMod
. Le (x `div` y)*y + (x `mod` y) == x
la loi est très bonne, mais arrondir la division vers l’infini négatif (division de Knuth) est souvent moins utile et moins efficace que de garantir que 0 <= x `mod` y < y
_ (Division euclidienne).
Si vous souhaitez uniquement tester la divisibilité, vous devez toujours utiliser rem
.
Essentiellement x `mod` y == 0
est équivalent à x `rem` y == 0
, mais rem
est plus rapide que mod
.