Diferença entre `mod` e` rem` em Haskell

130

Qual é exatamente a diferença entre mode remem Haskell?

Ambos parecem dar os mesmos resultados

*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
fonte
3
Não conheço Haskell, mas provavelmente é a mesma operação. modulus == remainder.
Matthew Scharley
Para ser justo, não era a mesma pergunta. A outra pergunta assumiu o entendimento da resposta a essa pergunta.
Dan Burton
@ Dan Lendo essa pergunta, por causa de outra pergunta que eu tinha ( stackoverflow.com/questions/5892188/… ), percebi o mesmo: /
Oscar Mederos
2
é a mesma diferença que entre divequot
newacct 04/04

Respostas:

181

Eles não são os mesmos quando o segundo argumento é negativo:

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2
Fred Foo
fonte
20
Eu tinha a mesma pergunta sobre reme modem Clojure, e essa era a resposta.
noahlz
11
Nem são os mesmos quando o primeiro argumento é negativo. Consulte stackoverflow.com/a/8111203/1535283 e stackoverflow.com/a/339823/1535283 para obter mais informações sobre essas operações complicadas.
Scott Olson
4
Também de stackoverflow.com/a/6964760/205521 , parece que remé o mais rápido.
Thomas Ahle 28/09
16
Embora essa resposta esteja correta, uma resposta que reivindique não mais do que "não é o mesmo" para uma pergunta "qual é a diferença" é muito ruim. Eu agradeceria se você pudesse expandir "como" eles são diferentes e alguns casos de uso provavelmente.
poitroae
59

Sim, essas funções agem de maneira diferente. Conforme definido na documentação oficial :

quot é a divisão inteira truncada em direção a zero

rem é um número inteiro restante, satisfazendo:

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

div é a divisão inteira truncada em direção ao infinito negativo

mod é um módulo inteiro, satisfazendo:

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

Você pode realmente notar a diferença quando usa um número negativo como segundo parâmetro e o resultado não é zero:

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
fonte
Seus últimos quatro exemplos provavelmente não são o que você quer dizer, uma vez que mode remassociado mais fortemente do que (-). Editei o seu comentário, pois parece que não consigo colocar coisas com várias linhas neste comentário.
precisa saber é o seguinte
1
@ErikHesselink: você introduziu um erro na sua edição. (-5) `mod` 3 == 1
Cheng Sun
@ChengSun Obrigado, eu consertei. Deve estar ativo após a revisão.
precisa saber é o seguinte
16

Praticamente falando:

Se você sabe que ambos os operandos são positivos, você deve geralmente usar quot, remou quotRempara a eficiência.

Se você não sabe que ambos os operandos são positivos, deve pensar em como deseja que os resultados sejam. Você provavelmente não quer quotRem, mas também não divMod. A (x `div` y)*y + (x `mod` y) == xlei é muito boa, mas a divisão de arredondamento em direção ao infinito negativo (divisão no estilo de Knuth) costuma ser menos útil e menos eficiente do que garantir isso 0 <= x `mod` y < y(divisão euclidiana).

dfeuer
fonte
5

Caso você queira apenas testar a divisibilidade, use sempre rem.

Essencialmente x `mod` y == 0é equivalente a x `rem` y == 0, mas remé mais rápido que mod.

sjakobi
fonte