พฤติกรรมของการแบ่งจำนวนเต็มคืออะไร?


209

ตัวอย่างเช่น,

int result;

result = 125/100;

หรือ

result = 43/100;

ผลลัพธ์จะเป็นพื้นของแผนกหรือไม่ พฤติกรรมที่กำหนดคืออะไร?


5
สรุป: ลงนามแบ่งจำนวนเต็มตัดต่อศูนย์ สำหรับผลลัพธ์ที่ไม่เป็นลบนี่จะเหมือนกับ floor (ปัดไปทาง -Infinity) (ระวังว่า C89 จะไม่รับประกันสิ่งนี้ดูคำตอบ)
Peter Cordes

5
ทุกคนพูดว่า "ตัดให้เป็นศูนย์" หรือ "เพดาน" หรือ "พื้น" เหมือนรหัสที่ใช้ในการตัดสินใจโดยไตร่ตรองว่าจะใช้เทคนิคใด ถ้ารหัสสามารถพูดได้ก็จะบอกว่า"I just throw the dam fraction part in the trash and move on with life"
ทิโมธี LJ Stewart

3
@ TimothyL.J.Stewart "code" กำลังตัดสินใจโดยเจตนา ตามข้อกำหนดคุณสมบัติการแบ่งจำนวนเต็มนั้นหมายถึง T (runcation) -division ด้วยเหตุนี้ตัวดำเนินการแบบโมดูโล / ส่วนที่เหลือจึงถูกใส่เข้าไปในภาษาที่แตกต่างจากภาษาอื่นเช่น Python หรือ Ruby ดูที่นี่สำหรับรายการวิธีที่ต่างกันที่ภาษาดำเนินการตัวดำเนินการ modulo และบทความนี้ซึ่งแสดงรายการอย่างน้อยห้าวิธีที่ภาษาโปรแกรมทั่วไปตัดสินใจที่จะทำ div / modulo
13steinj

1
@ 13steinj ฉันกำลังพูดถึงการเรียกขานต่อความคิดเห็นที่กลายเป็น "มันถูกตัดทอนลงเป็นศูนย์ ... ไม่มีพื้น ... ไม่ถ้ามันเป็นลบเพดาน ... " บางครั้งนักวิชาการไม่เผยแพร่ในอนาคตด้วยความทรงจำของมนุษย์ อย่างที่เราต้องการ แต่การรู้อย่างสังหรณ์ใจว่า "เศษส่วนถูกโยนทิ้ง" คุณสามารถได้รับคะแนนทางเทคนิค ช่างเป็นภาระที่หนักหน่วง แต่ปรีชานั้นเบาและสดชื่นเหมือนลมฉันจะอุ้มพวกมันไปไกลและกว้างเมื่อจำเป็นฉันจะรู้ว่าจะเริ่มที่ไหนดี เช่นเดียวกับกระดาษที่คุณเชื่อมโยงขอบคุณ
Timothy LJ Stewart

ฉันตอบ ที่นี่โดยเน้นที่หมวด Euclidean (ระหว่างการเล่นระหว่างการหารจำนวนเต็มและตัวดำเนินการโมดูลัส)
Picaud Vincent

คำตอบ:


182

ผลลัพธ์จะเป็นพื้นของแผนกหรือไม่ พฤติกรรมที่กำหนดคืออะไร?

ใช่ผลหารจำนวนเต็มของตัวถูกดำเนินการสองตัว

6.5.5 ตัวดำเนินการหลายตัว

6เมื่อจำนวนเต็มถูกหารผลลัพธ์ของ / โอเปอเรเตอร์คือความฉลาดทางพีชคณิตกับเศษส่วนที่ละทิ้ง 88)ถ้าความฉลาดทาง a / b แสดงออกได้การแสดงออก (a / b) * b + a% b จะเท่ากับ a

และเชิงอรรถที่เกี่ยวข้อง:

88) สิ่งนี้มักถูกเรียกว่า '' การตัดให้เป็นศูนย์ ''

แน่นอนว่าสองจุดที่ควรทราบคือ:

3การแปลงเลขคณิตปกติจะดำเนินการกับตัวถูกดำเนินการ

และ:

5ผลลัพธ์ของตัวดำเนินการ / คือผลหารจากส่วนของตัวถูกดำเนินการแรกโดยวินาที ผลลัพธ์ของตัวดำเนินการ% คือส่วนที่เหลือ ในการดำเนินการทั้งสองถ้าค่าของตัวถูกดำเนินการที่สองเป็นศูนย์พฤติกรรมจะไม่ได้กำหนด

[หมายเหตุ: เน้นเหมือง]


26
... เว้นแต่แน่นอนคุณจะหารจำนวนลบด้วยค่าบวก (หรือ vv) ซึ่งในกรณีนี้มันจะเป็นเพดาน
จะ

74
มันไม่ใช่พื้นหรือเพดานมันถูกตัดส่วนที่เป็นเศษส่วนมันแตกต่างจากแนวคิด!
lornova

38
@ Will A: ไม่มันหมายถึงการตัดทอนเข้าหาศูนย์ การโทรไปที่อื่นจะเพิ่มความสับสนดังนั้นโปรดงดเว้น
Martin York

44
อย่างน้อยจากมุมมองทางคณิตศาสตร์การตัดเข้าหาศูนย์จะเท่ากับ "ถ้า> 0 แล้วทำให้เพดานเป็นพื้นอื่น" ฉันคิดว่าเพียงแค่เรียกว่าการตัดทอนนั้นง่ายกว่าเรียกว่าพื้น / เพดาน แต่ก็ใช้ได้ทั้งคู่ ไม่ว่าประเด็นของ A จะถูกต้องหรือไม่: คำตอบของ Dirkgently นั้นไม่ถูกต้องบางส่วนเนื่องจากเขาระบุว่า OP นั้นถูกต้องเกี่ยวกับผลลัพธ์ที่เป็นพื้นของการแบ่ง
ไบรอัน

9
@ ฟิลิปพอตเตอร์: ฉันไม่คิดว่ามันถูกกำหนดใน C89 และมันไม่ได้อยู่ในมาตรฐาน 1998 C ++ ในหลักสูตรเหล่านั้น(a / b) * b + a % b == aจะต้องมีความพึงพอใจและค่าสัมบูรณ์ของa % bต้องน้อยกว่าaแต่ไม่ว่าจะa % bเป็นค่าลบสำหรับค่าลบaหรือbไม่ได้ระบุไว้
David Thornley

39

Dirkgently ให้คำอธิบายที่ยอดเยี่ยมของการหารจำนวนเต็มใน C99 แต่คุณควรรู้ด้วยว่าในการหารจำนวนเต็ม C89 ด้วยตัวถูกลบจะมีทิศทางที่กำหนดไว้

จากแบบร่าง ANSI C (3.3.5):

หากตัวถูกดำเนินการทั้งสองเป็นลบไม่ว่าผลลัพธ์ของตัวดำเนินการ / จะเป็นจำนวนเต็มที่มากที่สุดน้อยกว่าความฉลาดทางพีชคณิตหรือจำนวนเต็มที่น้อยที่สุดที่มากกว่าความฉลาดทางพีชคณิตเป็นการดำเนินการตามที่กำหนดเป็นสัญญาณของผลลัพธ์ของตัวดำเนินการ% หากสามารถหารผลหาร a / b ได้นิพจน์ (a / b) * b + a% b จะเท่ากับ a

ดังนั้นระวังตัวเลขติดลบเมื่อคุณติดกับคอมไพเลอร์ C89

มันเป็นเรื่องสนุกที่ C99 เลือกที่จะตัดให้เหลือศูนย์เพราะนั่นเป็นวิธีที่ FORTRAN ทำ ดูข้อความนี้ใน comp.std.c


2
และ C99 ฉบับร่าง N1256 คำนำวรรค 5 ระบุreliable integer divisionว่าเป็นคุณสมบัติภาษาใหม่ *-*น่าอัศจรรย์
Ciro Santilli 郝海东冠状病六四事件法轮功

การตัดทอนคือฮาร์ดแวร์ของ CPU ที่ใช้กันทั่วไป (เช่น x86) มีพฤติกรรมอย่างไรจึงเป็นการดีที่จะเลือกอีกวิธีหนึ่ง IDK ซึ่งมาก่อนความหมายของ Fortran หรือพฤติกรรมฮาร์ดแวร์ แต่ก็ไม่ใช่เรื่องบังเอิญเหมือนกัน
Peter Cordes

2
@PeterCordes: ฮาร์ดแวร์ CPU ทั่วไปส่วนใหญ่สามารถทำการแบ่งพื้นโดยค่าคงที่ส่วนใหญ่ได้เร็วกว่าที่พวกเขาสามารถทำการตัดส่วน IMHO คงจะดีกว่าที่มาตรฐานจะกล่าวexpr1 / expr2และexpr1 % expr2ต้องสอดคล้องกันเมื่อทั้งสองอินสแตนซ์ของการexpr1รวมวัตถุเดียวกันในลักษณะเดียวกันและในทำนองเดียวกันexpr2แต่การเลือกตัดทอนกับการแบ่งพื้นไม่ได้ระบุไว้เป็นอย่างอื่น ที่จะได้รับอนุญาตให้สร้างรหัสมีประสิทธิภาพมากขึ้นโดยไม่ทำลายความเข้ากันได้มาก (และการใช้งานที่สามารถทำเอกสารพฤติกรรมเฉพาะถ้าเอียง)
SuperCat

23

ในกรณีที่ผลลัพธ์เป็นลบ C ตัดทอนเป็น 0 แทนที่จะปูพื้น - ฉันเรียนรู้การอ่านนี้ว่าทำไมการแบ่งจำนวนเต็มของ Python ถึงชั้นที่นี่เสมอ: ทำไม Python Integer Division Floors


3
ฉันเห็นด้วยกับความคิดเห็นที่สงสัยว่าการลบ (neg% pos) เชิงลบเป็นประโยชน์หรือไม่ ในบันทึกที่เกี่ยวข้องฉันสงสัยว่าพฤติกรรมที่ไม่ถูกต้องทางคณิตศาสตร์ที่จำเป็นในบางกรณีของ "unsignedvar> Signvar" มีประโยชน์หรือไม่? ฉันสามารถเข้าใจเหตุผลที่ไม่ต้องการพฤติกรรมที่ถูกต้องเสมอ ฉันไม่เห็นเหตุผลที่ต้องการพฤติกรรมที่ผิด
supercat

8
+1 สำหรับการอ้างอิงที่ดีเยี่ยมว่าทำไมการปูพื้นเป็นพฤติกรรมที่ถูกต้องสำหรับการหารจำนวนเต็ม (ตรงกันข้ามกับคำจำกัดความของ C ซึ่งเสียและแทบไม่มีประโยชน์เลย)
.. GitHub หยุดช่วยน้ำแข็ง

@supercat พิจารณา: filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factor, valueซ้ำกับการเปลี่ยนแปลงค่านิยมของ มันทำให้การประมาณจำนวนเต็มเป็นเรื่องที่ดีสำหรับตัวกรอง lowpass ลำดับที่หนึ่งที่มีค่าคงที่เวลาk... แต่มันก็สมมาตรหากการหารถูกตัดทอนและcarryรับค่าลบ พฤติกรรมทั้งสองอย่างมีประโยชน์เป็นครั้งคราว
ฮอบส์

1
@ ฮอบส์: ฉันไม่คิดว่ารหัสข้างต้นจะทำงานได้อย่างสมบูรณ์เมื่อสัญญาณข้ามศูนย์ หากdivเป็นผู้ประกอบการส่วนปูพื้นและfactorเป็นเลขคี่จากนั้นจะให้ผลผลิตพฤติกรรมที่สะอาดและสมมาตรค่าทั้งหมดขึ้นอยู่กับfiltered += (filter+(factor div 2)) div factor INT_MAX-(factor div 2)
supercat

@supercat มันทำงานแม้ว่า; รหัสนั้นกลั่นเพียงเล็กน้อยจากสิ่งที่ฉันเคยทำงานในตัวควบคุมของนาฬิกาอะตอมอยู่พักหนึ่ง
hobbs

21

ใช่ผลลัพธ์จะถูกปัดเศษเป็นศูนย์เสมอ มันจะปัดไปหาค่าสัมบูรณ์ที่เล็กที่สุด

-5 / 2 = -2
 5 / 2 =  2

สำหรับค่าที่ลงชื่อไม่ได้ลงนามและไม่เป็นลบค่านี้จะเหมือนกับ floor (ปัดเศษไปยัง -Infinity)


43
การตัดไม่ใช่พื้น
dan04

9
@ dan04 ชั้นครับจะใช้ได้เฉพาะสำหรับจำนวนเต็มบวก :)
Leonid

13

ผลลัพธ์จะเป็นพื้นของแผนกหรือไม่

ไม่ผลลัพธ์จะแตกต่างกันไป

พฤติกรรมที่กำหนดคืออะไร?

เพื่อให้ชัดเจนรอบพื้นไปทางลบอนันต์ในขณะที่การแบ่งจำนวนเต็มรอบไปที่ศูนย์ (ตัด)

สำหรับค่าบวกพวกเขาเหมือนกัน

int integerDivisionResultPositive= 125/100;//= 1
double flooringResultPositive= floor(125.0/100.0);//=1.0

สำหรับค่าลบนี้จะแตกต่างกัน

int integerDivisionResultNegative= -125/100;//=-1
double flooringResultNegative= floor(-125.0/100.0);//=-2.0

0

ฉันรู้ว่าผู้คนตอบคำถามของคุณ แต่ในแง่คนธรรมดา:

5 / 2 = 2 // เนื่องจากทั้ง 5 และ 2 เป็นเลขจำนวนเต็มและการหารจำนวนเต็มจะตัดทอนทศนิยมเสมอ

5.0 / 2 or 5 / 2.0 or 5.0 /2.0 = 2.5 // ที่นี่ทั้ง 5 หรือ 2 หรือทั้งสองมีทศนิยมดังนั้นความฉลาดที่คุณจะได้รับจะเป็นทศนิยม

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