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

В чем именно разница между 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

Ответ 1

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

2 `mod` (-3)  ==  -1
2 `rem` (-3)  ==  2

Ответ 2

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

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

 

Ответ 3

Практически говоря:

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

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

Ответ 4

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

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