Разница между `mod` и` rem` в Haskell

130

В чем именно разница между modи remв Haskell?

Оба, кажется, дают одинаковые результаты

*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
Не знаю Haskell, но, скорее всего, это одна и та же операция. modулус == remайндер.
Мэтью Шарли
Честно говоря, это был не тот вопрос. Другой вопрос предполагал понимание ответа на этот вопрос.
Дэн Бертон
@Dan Прочитав этот вопрос, из-за другого вопроса, который у меня был ( stackoverflow.com/questions/5892188/… ), я понял то же самое: /
Оскар Медерос
2
это та же разница, что и между divиquot
newacct

Ответы:

181

Они не то же самое, когда второй аргумент отрицательный:

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2
Фред Фу
источник
20
У меня был тот же вопрос о Clojure remи modв нем, и это был ответ.
noahlz
11
Они не одинаковы и при отрицательном первом аргументе. См. Stackoverflow.com/a/8111203/1535283 и stackoverflow.com/a/339823/1535283 для получения дополнительной информации об этих сложных операциях.
Скотт Олсон
4
Также из stackoverflow.com/a/6964760/205521 кажется, что remэто самый быстрый.
Thomas Ahle
16
Хотя это правильный ответ, ответ, утверждающий не более чем «не то же самое» на вопрос «в чем разница», очень плох. Я был бы рад, если бы вы могли подробнее рассказать, «как» они разные, и, возможно, некоторые варианты использования.
poitroae
59

Да, эти функции действуют по-другому. Как определено в официальной документации :

quot целочисленное деление, усеченное до нуля

rem - целочисленный остаток, удовлетворяющий:

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

div целочисленное деление, усеченное до отрицательной бесконечности

mod является целочисленным модулем, удовлетворяющим:

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

Вы действительно можете заметить разницу, если вы используете отрицательное число в качестве второго параметра, а результат не равен нулю:

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

 

Джузеппе Бертоне
источник
Ваши последние четыре примера, вероятно, не то, что вы имеете в виду, так как modи remассоциация сильнее, чем (-). Я отредактировал ваш комментарий, так как не могу поместить в него многострочный материал.
Эрик Хесселинк,
1
@ErikHesselink: вы ввели ошибку при редактировании. (-5) `mod` 3 == 1
Ченг Сун
@ChengSun Спасибо, я исправил. Должен быть доступен после просмотра.
Эрик Хесселинк,
16

Практически:

Если вы знаете , оба операнда положительны, обычно вы должны использовать quot, remили quotRemдля повышения эффективности.

Если вы не знаете, что оба операнда положительны, вы должны подумать о том, как должны выглядеть результаты. Вы, наверное, не хотите quotRem, но, возможно, и не хотите divMod. Этот (x `div` y)*y + (x `mod` y) == xзакон очень хорош, но округление деления до отрицательной бесконечности (деление в стиле Кнута) часто менее полезно и менее эффективно, чем обеспечение этого 0 <= x `mod` y < y(евклидово деление).

dfeuer
источник
5

Если вы хотите только проверить делимость, вы всегда должны использовать rem.

По сути x `mod` y == 0эквивалентно x `rem` y == 0, но remработает быстрее mod.

sjakobi
источник