ความแตกต่างระหว่าง "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 แต่น่าจะเป็นการดำเนินการเดียวกัน modulus == remainder
Matthew Scharley

เพื่อความเป็นธรรมมันไม่ใช่คำถามเดียวกัน คำถามอื่นถือว่าเข้าใจคำตอบของคำถามนี้
Dan Burton

@ แดนอ่านคำถามนั้นเพราะคำถามอื่นที่ฉันมี ( stackoverflow.com/questions/5892188/… ) ฉันก็รู้เหมือนกัน: /
Oscar Mederos

2
มันเป็นความแตกต่างที่เหมือนกันทั้งระหว่างdivและquot
newacct

คำตอบ:


181

ไม่เหมือนกันเมื่ออาร์กิวเมนต์ที่สองเป็นลบ:

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

20
ฉันมีคำถามเดียวกันเกี่ยวกับremและmodใน Clojure และนี่คือคำตอบ
noahlz

11
ไม่เหมือนกันเมื่ออาร์กิวเมนต์แรกเป็นลบ โปรดดูstackoverflow.com/a/8111203/1535283และstackoverflow.com/a/339823/1535283สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการดำเนินการที่ยุ่งยากเหล่านี้
Scott Olson

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 (-)ฉันแก้ไขความคิดเห็นของคุณแล้วเนื่องจากดูเหมือนว่าฉันจะใส่หลายบรรทัดในความคิดเห็นนี้ไม่ได้
Erik Hesselink

1
@ErikHesselink: คุณแนะนำข้อผิดพลาดในการแก้ไขของคุณ (-5) `mod` 3 == 1
Cheng Sun

@ChengSun ขอบคุณฉันได้รับการแก้ไขแล้ว ควรใช้งานได้หลังจากตรวจสอบแล้ว
Erik Hesselink

16

พูดจริง:

ถ้าคุณรู้ว่าทั้งสองตัวถูกดำเนินการเป็นบวกที่คุณมักจะควรใช้quot, remหรือquotRemให้มีประสิทธิภาพ

หากคุณไม่ทราบว่าตัวถูกดำเนินการทั้งสองเป็นค่าบวกคุณต้องคิดว่าคุณต้องการให้ผลลัพธ์เป็นอย่างไร คุณอาจไม่ต้องการquotRemแต่คุณอาจไม่ต้องการdivModเช่นกัน (x `div` y)*y + (x `mod` y) == xกฎหมายเป็นหนึ่งที่ดีมาก แต่ส่วนปัดเศษไปยังอินฟินิตี้ลบ (ส่วนสไตล์นู) มักจะเป็นประโยชน์น้อยลงและมีประสิทธิภาพน้อยกว่ามั่นใจว่า0 <= x `mod` y < y(การแบ่งยุคลิด)


5

remในกรณีที่คุณต้องการสำหรับการทดสอบหารคุณควรใช้

เป็นหลักx `mod` y == 0เทียบเท่ากับx `rem` y == 0แต่จะเร็วกว่าremmod

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.