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

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

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

 


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


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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.