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

130

Quelle est exactement la différence entre modet remdans 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
Oscar Mederos
la source
3
Je ne connais pas Haskell, mais il s'agit probablement de la même opération. modulus == remainder.
Matthew Scharley
Pour être honnête, ce n'était pas la même question. L'autre question supposait la compréhension de la réponse à cette question.
Dan Burton
@Dan En lisant cette question, à cause d'une autre question que j'avais ( stackoverflow.com/questions/5892188/… ), j'ai réalisé la même chose: /
Oscar Mederos
2
c'est la même différence qu'entre divetquot
newacct

Réponses:

181

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

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2
Fred Foo
la source
20
J'avais la même question sur remet moddans Clojure, et c'était la réponse.
noahlz du
11
Ils ne sont pas non plus les mêmes lorsque le premier argument est négatif. Voir stackoverflow.com/a/8111203/1535283 et stackoverflow.com/a/339823/1535283 pour plus d'informations sur ces opérations délicates.
Scott Olson
4
Aussi sur stackoverflow.com/a/6964760/205521, il semble que remc'est le plus rapide.
Thomas Ahle
16
Bien que cette réponse soit correcte, une réponse qui ne prétend rien de plus que "pas la même chose" à une question "quelle est la différence" est très mauvaise. Je vous serais reconnaissant si vous pouviez développer "en quoi" ils sont différents et probablement certains cas d'utilisation.
poitroae
59

Oui, ces fonctions agissent différemment. Tel que défini dans la 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 la division entière tronquée vers l'infini négatif

mod est le 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 comme deuxième paramètre et que le résultat n'est pas zéro:

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

 

Giuseppe Bertone
la source
Vos quatre derniers exemples ne sont probablement pas ce que vous voulez dire, puisque modet remassociez plus fortement que (-). J'ai modifié votre commentaire car je n'arrive pas à mettre des éléments sur plusieurs lignes dans ce commentaire.
Erik Hesselink
1
@ErikHesselink: vous avez introduit une erreur avec votre modification. (-5) `mod` 3 == 1
Cheng Sun
@ChengSun Merci, je l'ai corrigé. Devrait être en direct après examen.
Erik Hesselink
16

Pratiquement parlant:

Si vous connaissez les deux opérandes sont positifs, vous devez utiliser habituellement quot, remou l' quotRemefficacité.

Si vous ne savez pas que les deux opérandes sont positifs, vous devez réfléchir à ce à quoi vous voulez que les résultats ressemblent. Vous ne voulez probablement pas quotRem, mais vous ne voulez peut-être pas non divModplus. La (x `div` y)*y + (x `mod` y) == xloi est très bonne, mais arrondir la division vers l'infini négatif (division de style Knuth) est souvent moins utile et moins efficace que d'assurer cela 0 <= x `mod` y < y(division euclidienne).

dfeuer
la source
5

Si vous souhaitez uniquement tester la divisibilité, vous devez toujours utiliser rem.

Équivaut essentiellement x `mod` y == 0à x `rem` y == 0, mais remest plus rapide que mod.

Sjakobi
la source