Sự khác biệt giữa `mod` và` rem` trong Haskell


130

Chính xác thì sự khác biệt giữa modremtrong Haskell là gì?

Cả hai dường như cho kết quả như nhau

*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
Không biết Haskell, nhưng có khả năng đây là cùng một hoạt động. modulus == remainder.
Matthew Scharley

Công bằng mà nói, đó không phải là câu hỏi tương tự. Các câu hỏi khác giả định hiểu câu trả lời cho câu hỏi này.
Dan Burton

@Dan Đọc câu hỏi đó, vì một câu hỏi khác mà tôi có ( stackoverflow.com/questions/5892188/iêu ), tôi nhận ra điều tương tự: /
Oscar Mederos

2
đó là sự khác biệt giống như giữa divquot
newacct

Câu trả lời:


181

Chúng không giống nhau khi đối số thứ hai là phủ định:

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

20
Tôi đã có cùng một câu hỏi về remmodtrong Clojure, và đây là câu trả lời.
noahlz

11
Chúng cũng không giống nhau khi đối số đầu tiên là phủ định. Xem stackoverflow.com/a/8111203/1535283stackoverflow.com/a/339823/1535283 để biết thêm thông tin về các hoạt động khó khăn này.
Scott Olson

4
Cũng từ stackoverflow.com/a/6964760/205521 có vẻ như remlà nhanh nhất.
Thomas Ahle

16
Mặc dù câu trả lời này là chính xác, nhưng một câu trả lời khẳng định không quá "không giống nhau" cho một câu hỏi "sự khác biệt" là một câu hỏi rất tệ. Tôi sẽ hoan nghênh nếu bạn có thể mở rộng về "cách" chúng khác nhau và một số cách sử dụng có thể.
poitroae

59

Vâng, những chức năng đó hoạt động khác nhau. Như được định nghĩa trong tài liệu chính thức :

quot là phép chia số nguyên bị cắt về không

rem là số nguyên còn lại, thỏa mãn:

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

div là phép chia số nguyên bị cắt về phía vô cực âm

mod là mô đun số nguyên, thỏa mãn:

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

Bạn thực sự có thể nhận thấy sự khác biệt khi bạn sử dụng số âm làm tham số thứ hai và kết quả không phải là 0:

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

 


Bốn ví dụ cuối cùng của bạn có lẽ không phải là ý bạn, vì modremliên kết mạnh mẽ hơn (-). Tôi đã chỉnh sửa nhận xét của bạn vì tôi dường như không thể đặt nội dung nhiều dòng trong nhận xét này.
Erik Hesselink

1
@ErikHesselink: bạn đã giới thiệu một lỗi với chỉnh sửa của mình. (-5) `mod` 3 == 1
Cheng Sun

@ChengSun Cảm ơn, tôi đã sửa nó. Nên sống sau khi xem xét.
Erik Hesselink

16

Nói thực tế:

Nếu bạn biết cả hai toán hạng là tích cực, bạn thường nên sử dụng quot, remhoặc quotRemcho hiệu quả.

Nếu bạn không biết cả hai toán hạng đều dương, bạn phải suy nghĩ về kết quả bạn muốn. Bạn có thể không muốn quotRem, nhưng bạn cũng có thể không muốn divMod. Các (x `div` y)*y + (x `mod` y) == xluật là một trong những rất tốt, nhưng làm tròn phận về phía vô cực âm (Knuth phân chia phong cách) thường là ít hữu ích và kém hiệu quả hơn so với việc đảm bảo rằng 0 <= x `mod` y < y(phép chia có dư).


5

Trong trường hợp bạn chỉ muốn kiểm tra tính phân chia, bạn nên luôn luôn sử dụng rem.

Về cơ bản x `mod` y == 0là tương đương x `rem` y == 0, nhưng remnhanh hơn mod.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.