คอมพิวเตอร์จะพยายามหารด้วยศูนย์หรือไม่


59

เราทุกคนรู้0/0เป็นUndefinedและกลับข้อผิดพลาดถ้าผมจะใส่ลงในเครื่องคิดเลขและถ้าผมจะสร้างโปรแกรม (ใน C อย่างน้อย) OS จะยุติมันเมื่อฉันพยายามที่จะหารด้วยศูนย์

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


10
0/0 ไม่ได้นิยามหมายเลขอื่น ๆ / 0 เป็นข้อผิดพลาดชนิดอื่นคุณดูเหมือนสับสนทั้งสอง
edc65

7
ตัวเลขใด ๆ ที่หารด้วย 0 จะไม่ถูกกำหนดและพูดทางคณิตศาสตร์
ManoDestra

12
@jwg: "ถ้ามันมีค่ามันจะเป็น 1" - ไม่จำเป็นต้อง; มีสาขาทั้งของคณิตศาสตร์ที่ทุ่มเทให้กับสิ่งที่มีค่าอาจจะอยู่ในสถานการณ์ที่แตกต่างกัน :)
psmears

11
ชี้แจงคำศัพท์ที่นี่ 0/0 เรียกว่ารูปแบบที่ไม่แน่นอนในขณะที่ x / 0 ภัณฑ์xคือไม่ได้กำหนด การคำนวณที่ลงท้ายด้วย 0/0 สามารถคำนวณได้ในวิธีที่แตกต่างกันในการให้คำตอบจริงในขณะที่ x / 0 นั้นไม่มีความหมาย
ยุค

9
@ jwg คุณอาจสนใจกฎของ l'hopital แล้ว มีบางกรณีที่ 0/0 ไม่ได้หมายความถึงค่าของ 1
d0nut

คำตอบ:


74

CPU มีการตรวจจับในตัว สถาปัตยกรรมชุดคำสั่งส่วนใหญ่ระบุว่า CPU จะดักจับตัวจัดการข้อยกเว้นสำหรับจำนวนเต็มหารด้วยศูนย์ (ฉันไม่คิดว่ามันจะสนใจถ้าเงินปันผลเป็นศูนย์)

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

(ฮาร์ดแวร์มักจะทำงานอย่างนั้นทำหลายอย่างพร้อมกันแล้วเลือกผลลัพธ์ที่เหมาะสมหลังจากนั้นเพราะการดำเนินการแต่ละอย่างสามารถเริ่มต้นได้ทันทีแทนที่จะเป็นลำดับในการเลือกการดำเนินการที่เหมาะสม)

กลไกดักจับข้อยกเว้นเดียวกันจะใช้เมื่อเปิดการตรวจจับล้นซึ่งคุณมักจะถามโดยใช้คำสั่ง add / sub / mul อื่น (หรือตั้งค่าสถานะตามคำแนะนำเหล่านั้น)

ส่วนจุดลอยตัวยังมีการตรวจจับสำหรับการหารด้วยศูนย์ แต่ส่งกลับค่าที่แตกต่าง ( IEEE 754ระบุNaN ) แทนการดักจับไปที่ตัวจัดการข้อยกเว้น


หากสมมุติว่า CPU ตัดการตรวจจับใด ๆ เพื่อพยายามหารด้วยศูนย์ปัญหาอาจรวมถึง:

  • การแขวน CPU (เช่นใน inf. loop) - สิ่งนี้อาจเกิดขึ้นหาก CPU ใช้อัลกอริทึมในการหารที่จะหยุดเมื่อตัวเศษน้อยกว่าตัวหาร (ในค่าสัมบูรณ์) แฮงค์แบบนี้จะนับว่าพังซีพียู
  • a (อาจเป็นไปได้) คำตอบขยะถ้า CPU ใช้ตัวนับเพื่อยุติการหารด้วยจำนวนขั้นตอนการหารที่เป็นไปได้สูงสุด (เช่น 31 หรือ 32 บนเครื่อง 32 บิต)

51
@Ankush "ระบบล่ม" ไม่ใช่สิ่งที่เกิดขึ้นจริงในระดับ CPU พฤติกรรมที่เป็นไปได้มากที่สุดของซีพียูที่ไม่ได้ดักจับการหารด้วยศูนย์จะเป็นเพียงการดำเนินการหารทำให้เกิดผลลัพธ์ที่ไร้สาระและยังคงดำเนินต่อไป เช่นเดียวกับเมื่อคุณเพิ่มจำนวนเต็มสองจำนวนที่เกิดขึ้นกับการโอเวอร์โฟลว์
Ixrec

6
สำหรับจุดลอยตัวตัวเลือกระหว่าง "NaN" และ "กับดัก" มักจะสามารถตั้งค่าได้โดยการพลิกธงใน FPU
Vatine

10
@Ankush ในกรณีที่สิ่งที่ lxrec พูดไม่ชัดเจน: เท่าที่ซีพียูเกี่ยวข้องไม่มีสิ่งใดที่เป็นความผิดพลาด
user253751

7
@Ankush มีบางสถานการณ์ที่ทำให้เกิดระดับ "ระบบล่ม" ของ CPU ในกรณีเหล่านั้นเรากำลังพูดถึงสิ่งต่าง ๆ เช่นการปิดระบบป้องกันความร้อน (การป้องกันความร้อนสูงเกินไป) ความผิดปกติสามประการและสถานการณ์ที่คล้ายคลึงกัน ความผิดพลาดเกือบทุกครั้งที่คุณจะพบในการใช้งานทั่วไปรวมถึงopcodes ที่ไม่ถูกต้องได้รับการจัดการโดยการดักจับและการกู้คืนในบางลักษณะหรือเพียงแค่ละเว้นข้อผิดพลาดและดำเนินการต่อในสภาวะที่ไม่สะอาด
CVn

8
หากคุณไม่ได้ดักการหารด้วยศูนย์ผลลัพธ์จะเป็น "การไม่ได้กำหนดพฤติกรรม" หมายความว่าคอมพิวเตอร์อาจทำอะไรก็ได้ มันอาจเป็นตามที่ Bergi กล่าวถึงเข้าสู่วงบั๊กกี้แล้วแขวน มันอาจจะเอาท์พุทบิตที่ไม่ระบุชนิดของบิตที่เกิดขึ้นกับสิ่งที่เกิดขึ้นจากการใช้ตรรกะการหาร (จำไว้ว่าคอมพิวเตอร์ไม่ได้ "หาร" ในแง่คณิตศาสตร์มันทำการดำเนินการกับตัวเลขสองจำนวน ที่เรามักจะเรียกง่ายๆว่า "การหาร" ..
Cort Ammon

34

ขึ้นอยู่กับภาษาบนคอมไพเลอร์ไม่ว่าคุณจะใช้จำนวนเต็มหรือตัวเลขทศนิยมและอื่น ๆ

สำหรับจำนวนจุดลอยตัวการใช้งานส่วนใหญ่ใช้มาตรฐาน IEEE 754โดยที่การหารด้วย 0 ถูกกำหนดไว้อย่างดี 0/0ให้ผลลัพธ์ที่ชัดเจนของNaN (ไม่ใช่-a -number) และ x / 0 สำหรับ x + 0 ให้ + + Infinity หรือ -Infinity ขึ้นอยู่กับเครื่องหมายของ x

ในภาษาเช่น C, C ++ ฯลฯ การหารด้วยศูนย์จะเรียกใช้พฤติกรรมที่ไม่ได้กำหนด ดังนั้นตามคำจำกัดความของภาษาสิ่งที่สามารถเกิดขึ้นได้ โดยเฉพาะสิ่งที่คุณไม่ต้องการให้เกิดขึ้น เหมือนทุกอย่างทำงานได้อย่างสมบูรณ์แบบเมื่อคุณเขียนโค้ดและทำลายข้อมูลเมื่อลูกค้าของคุณใช้งาน ดังนั้นจากจุดภาษาของมุมมองไม่ทำเช่นนี้ บางภาษารับประกันว่าใบสมัครของคุณจะผิดพลาด มันขึ้นอยู่กับพวกเขาว่าจะใช้งานอย่างไร สำหรับภาษาเหล่านั้นการหารด้วยศูนย์จะมีปัญหา

โปรเซสเซอร์หลายตัวมีคำสั่ง "แบ่ง" ในตัวซึ่งจะทำงานแตกต่างกันไปขึ้นอยู่กับโปรเซสเซอร์ สำหรับโปรเซสเซอร์ Intel 32 บิตและ 64 บิตคำแนะนำ "แบ่ง" จะทำให้แอปพลิเคชันของคุณเสียหายเมื่อคุณพยายามหารด้วยศูนย์ โปรเซสเซอร์อื่นอาจทำงานแตกต่างกัน

หากคอมไพเลอร์ตรวจพบว่าการหารด้วยศูนย์จะเกิดขึ้นเมื่อคุณเรียกใช้งานโค้ดบางส่วนและคอมไพเลอร์ดีสำหรับผู้ใช้มันอาจเป็นคำเตือนให้คุณและสร้างคำสั่ง "หาร" ในตัวเพื่อให้พฤติกรรมนั้นเป็น เหมือนกัน.


22
"ในโปรเซสเซอร์ Intel 32 บิตและ 64 บิตคำแนะนำ" แบ่ง "จะทำให้แอปพลิเคชันของคุณทำงานล้มเหลวเมื่อคุณพยายามหารด้วยศูนย์" ต้องการการอ้างอิง ซีพียูไม่มีความคิดใด ๆ เกี่ยวกับแอปพลิเคชันพวกเขาดำเนินการคำสั่งและ (ถ้าเรารวม MMU) บังคับใช้การ จำกัด การเข้าถึงหน่วยความจำ (ยกเว้นในวงแหวน 0หรือเทียบเท่าในสถาปัตยกรรมที่ไม่ใช่ Intel-x86) คำสั่งนั้นเป็นส่วนหนึ่งของแอปพลิเคชัน A มากกว่าแอปพลิเคชัน B หรือระบบปฏิบัติการคอมโพเนนต์ C ไม่เกี่ยวข้องกับ CPU ไม่ว่าคำสั่งนั้นจะเป็นคำสั่ง X หรือใช้หน่วยความจำที่อยู่ Y นั้นสัมพันธ์กันหรือไม่
CVn

1
หากต้องการเพิ่มใน @ MichaelKjörlingความคิดเห็น: ระบบปฏิบัติการมีวิธีการไม่แจ้งแอปพลิเคชันของข้อผิดพลาดนี้ (และข้อผิดพลาดประเภทอื่น ๆ ) ในหน้าต่างโลกมันเป็นEXCEPTION_INT_DIVIDE_BY_ZEROค่าในการEXCEPTION_RECORDที่จะได้รับการจัดการโดย (หวังว่า) ติดตั้งStructed การจัดการข้อยกเว้น Handler
user45891

1
บางครั้งพวกเขาทำสิ่งอื่นนอกเหนือจากการรับประกันว่าแอปของคุณจะผิดพลาด ตัวอย่างเช่นหลายภาษา / แพลตฟอร์มรับประกันว่าพวกเขาจะโยนข้อยกเว้นในการหารด้วยศูนย์ จากนั้นคุณสามารถจับและจัดการข้อยกเว้นดังกล่าวโดยไม่ต้องหยุดทำงาน
reirab

2
คุณสามารถลบ "may" ภายใน "ตัวประมวลผลอื่นอาจทำงานต่างกัน": บนแพลตฟอร์ม PowerPC แผนกจะสร้างผลลัพธ์เป็นศูนย์จากการหารด้วยศูนย์ ซึ่งมีประโยชน์มากกว่าพฤติกรรมการตื่นตระหนกของแพลตฟอร์ม X86
cmaster

13

ดูเหมือนว่าคุณกำลังสงสัยว่าจะเกิดอะไรขึ้นถ้ามีคนสร้างซีพียูที่ไม่ได้ตรวจสอบอย่างชัดเจนก่อนที่จะแบ่งศูนย์ สิ่งที่จะเกิดขึ้นนั้นขึ้นอยู่กับการดำเนินงานของแผนก การใช้งานชนิดหนึ่งจะสร้างผลลัพธ์ที่มีการตั้งค่าบิตทั้งหมดเช่น 65535 บน CPU 16 บิต อื่นอาจวางสาย


1

แต่สิ่งที่ฉันสงสัยคือถ้าคอมพิวเตอร์พยายามแบ่งเป็นศูนย์หรือว่ามันมี "การป้องกันในตัว" ดังนั้นเมื่อมัน "เห็น" 0/0 มันกลับข้อผิดพลาดก่อนที่จะพยายามคำนวณมัน?

เนื่องจากx/0ทำให้ไม่รู้สึกระยะเวลาที่คอมพิวเตอร์จะต้องตรวจสอบการหารด้วยศูนย์ มีปัญหาอยู่ที่นี่: โปรแกรมเมอร์ต้องการคำนวณ(a+b)/cโดยไม่ต้องคอยตรวจสอบว่าการคำนวณนั้นสมเหตุสมผลหรือไม่ การตอบสนองต่อสิ่งที่อยู่ด้านล่างเพื่อหารด้วยศูนย์โดย CPU + หมายเลขชนิด + ระบบปฏิบัติการ + ภาษาคือการทำบางสิ่งที่ค่อนข้างรุนแรง (เช่นขัดข้องของโปรแกรม) หรือทำสิ่งที่เกินควร (เช่นสร้างค่าที่ไม่ทำให้ ความรู้สึกเช่นจุดลอยตัว IEEE NaN, ตัวเลขที่เป็น "ไม่ใช่ตัวเลข")

ในการตั้งค่าธรรมดาโปรแกรมเมอร์คาดว่าจะรู้ว่า(a+b)/cเหมาะสม ในบริบทนี้ไม่มีเหตุผลที่จะตรวจสอบการหารด้วยศูนย์ หากการหารด้วยศูนย์เกิดขึ้นและหากภาษาเครื่อง + ภาษาที่ใช้งาน + ข้อมูลชนิด + การตอบสนองของระบบปฏิบัติการนี้คือการทำให้โปรแกรมขัดข้องนั่นไม่เป็นไร หากการตอบสนองคือการสร้างค่าที่อาจก่อให้เกิดมลพิษในที่สุดทุกหมายเลขในโปรแกรมก็ไม่เป็นไรเช่นกัน

ทั้ง "สิ่งที่รุนแรง" หรือ "ใจดีมากเกินไป" เป็นสิ่งที่ถูกต้องในโลกของการคำนวณความน่าเชื่อถือสูง การตอบสนองเริ่มต้นเหล่านั้นอาจฆ่าผู้ป่วยชนเครื่องบินหรือระเบิดในที่ผิด ในสภาพแวดล้อมที่มีความน่าเชื่อถือสูงโปรแกรมเมอร์ที่เขียน(a+b)/cจะถูกเลือกให้ตายระหว่างการตรวจสอบโค้ดหรือในยุคปัจจุบันบางทีเครื่องมืออาจถูกเลือกให้ตายโดยอัตโนมัติโดยการตรวจสอบ verboten constructs ในสภาพแวดล้อมนี้โปรแกรมเมอร์นั้นควรเขียนอะไรบางอย่างตามบรรทัดของdiv(add(a,b),c)(และอาจตรวจสอบสถานะข้อผิดพลาด) ภายใต้ประทุนฟังก์ชั่นdiv(และยังadd) แมโคร / ป้องกันการหารด้วยศูนย์ (หรือล้นในกรณีของadd) สิ่งที่การป้องกันนั้นนำมาใช้นั้นเฉพาะเจาะจงมาก


เพียงเพราะ NaN ไม่เชื่อฟังเลขคณิตที่คุณเรียนในโรงเรียนไม่ได้หมายความว่าไม่มีเหตุผล มันเชื่อฟังเลขคณิตที่แตกต่างกัน
Caleth

-2

เรารู้แล้วว่าตอนนี้x/0และ0/0ไม่มีคำตอบที่ชัดเจน จะเกิดอะไรขึ้นถ้าคุณพยายามคำนวณ0/0ต่อไป

ในระบบที่ทันสมัยการคำนวณที่ถูกส่งไปยัง MPU ภายใน CPU NaNและมีการตั้งค่าสถานะเป็นการดำเนินการที่ผิดกฎหมายกลับ

ในระบบที่เก่ากว่ามากเช่นคอมพิวเตอร์ในบ้านยุค 80 ที่ไม่มีการแบ่งบนชิปการคำนวณจะทำโดยซอฟต์แวร์ใดก็ตามที่ทำงานอยู่ มีตัวเลือกที่เป็นไปได้ไม่กี่:

  • ลบสำเนาที่เล็กลงและเล็กลงของตัวหารจนกระทั่งค่าเป็นศูนย์และติดตามว่าสำเนาที่มีขนาดถูกลบออก
    • หากตรวจสอบศูนย์ก่อนการลบครั้งแรกมันจะออกอย่างรวดเร็วและผลลัพธ์จะเป็น 0
    • หากสันนิษฐานว่าจะต้องสามารถลบอย่างน้อยหนึ่งครั้งผลจะเป็น 1
  • คำนวณลอการิทึมของตัวเลขทั้งสองลบออกแล้วเพิ่มeไปตามกำลังของผลลัพธ์ วิธีที่ไม่มีประสิทธิภาพมากเมื่อเทียบกับวิธีการลบข้างต้น แต่ถูกต้องทางคณิตศาสตร์
    • โอเวอร์โฟลว์อาจเกิดขึ้นขณะพยายามคำนวณlog(0)และซอฟต์แวร์อาจใช้การจัดการข้อผิดพลาดตามปกติหรือเกิดข้อผิดพลาด
    • ซอฟต์แวร์อาจสมมติว่าลอการิทึมทั้งหมดสามารถคำนวณได้ในจำนวนขั้นตอนคงที่และส่งคืนค่าที่มีขนาดใหญ่ แต่ไม่ถูกต้อง เนื่องจากลอการิทึมทั้งสองจะเท่ากันความแตกต่างก็คือ0และ e 0 = 1 ทำให้ได้ผลลัพธ์1

กล่าวอีกนัยหนึ่งก็คือการดำเนินการขึ้นอยู่กับสิ่งที่จะเกิดขึ้นและมันเป็นไปได้ที่จะเขียนซอฟต์แวร์ที่ให้ผลลัพธ์ที่ถูกต้องและคาดเดาได้สำหรับทุกค่า แต่ดูเหมือนว่าค่าแปลก ๆ สำหรับ0/0สิ่งนั้น


3
คำถามนี้เกี่ยวกับการหารด้วยศูนย์ในจำนวนเต็มและไม่มีสิ่งเช่นNaNในจำนวนเต็ม
David Hammen

3
CPU จะไม่มีการคำนวณบันทึกและลบเพื่อคำนวณผลลัพธ์ของการหาร เวลาสอนลอการิทึมนั้นมีขนาดของคำสั่งมากกว่าหนึ่งส่วน ค่าของบันทึก (0) คืออะไร?
wallyk

1
@DavidHammen OP ไม่เคยพูดถึงจำนวนเต็มและไม่เคยมีใครแสดงความคิดเห็นกับคำถาม จำนวนเต็มถูกกล่าวถึงในคำตอบเท่านั้น
CJ Dennis

@wallyk ฉันได้กล่าวแล้วในคำตอบของฉันว่าลอการิทึมนั้นมีvery inefficientไว้สำหรับการแบ่ง ค่าใช้จ่ายสำหรับการคำนวณคือ (บวก = การลบ) <= การคูณ <= การหาร หากคุณไม่มี MPU ที่สามารถทำการหารในรอบสัญญาณนาฬิกาเท่ากันกับการเพิ่ม (โดยปกติจะเป็นหนึ่ง) การหารนั้นจะมีราคาแพงกว่าการบวกและการลบและมักจะแพงกว่าการคูณด้วย
CJ Dennis
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.