Ответ 1
Они не совпадают, если второй аргумент отрицательный:
2 `mod` (-3) == -1
2 `rem` (-3) == 2
В чем именно разница между 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
Они не совпадают, если второй аргумент отрицательный:
2 `mod` (-3) == -1
2 `rem` (-3) == 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
Практически говоря:
Если вы знаете, что оба операнда положительны, вы обычно должны использовать quot
, rem
или quotRem
для эффективности.
Если вы не знаете, что оба операнда положительны, вам нужно подумать о том, как вы хотите, чтобы результаты выглядели. Вероятно, вы не хотите quotRem
, но вам может и не понадобиться divMod
. Закон (x `div` y)*y + (x `mod` y) == x
является очень хорошим, но округление до отрицательной бесконечности (разделение стиля Кнута) часто менее полезно и менее эффективно, чем обеспечение 0 <= x `mod` y < y
(евклидова деления).
Если вы хотите проверить только делимость, вы всегда должны использовать rem
.
По существу x `mod` y == 0
эквивалентен x `rem` y == 0
, но rem
быстрее, чем mod
.