web-dev-qa-db-fra.com

Différence entre `mod` et` rem` dans Haskell

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
114
Oscar Mederos

Ils ne sont pas les mêmes quand le deuxième argument est négatif:

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2
164
Fred Foo

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

51
Giuseppe Bertone

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).

10
dfeuer

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.

4
sjakobi