อะไรคือความแตกต่างระหว่าง int ที่ลงนามและไม่ได้ลงนาม


94

Int ที่ลงนามและไม่ได้ลงนามแตกต่างกันอย่างไร


5
นี่เป็นคำถามที่แท้จริงและคำตอบนั้นไม่ง่าย แต่ค่อนข้างละเอียดอ่อน
R .. GitHub STOP HELPING ICE

การลงคะแนนเพื่อเปิดอีกครั้ง อาจจะซ้ำกัน แต่เป็นคำถามที่แท้จริง
Brian


ควรเพิ่มแท็กเพิ่มเติมเนื่องจากมีหลายภาษาใช้
Juan Boero

คำถามนี้อาจต้องใช้บทเพื่ออธิบายอย่างละเอียด หากคุณต้องการทราบรายละเอียดโปรดตรวจสอบUnsigned และ Signed จำนวนเต็มสำหรับคำอธิบายเพิ่มเติม
ไม่ระบุชื่อ

คำตอบ:


115

ดังที่คุณทราบints จะถูกเก็บไว้ภายในเป็นไบนารี โดยทั่วไปแล้วจะintมี 32 บิต แต่ในบางสภาพแวดล้อมอาจมี 16 หรือ 64 บิต (หรือแม้กระทั่งตัวเลขที่แตกต่างกัน แต่โดยปกติแล้วไม่จำเป็นต้องมีกำลังสอง)

แต่สำหรับตัวอย่างนี้ลองดูจำนวนเต็ม 4 บิต เล็ก แต่มีประโยชน์เพื่อวัตถุประสงค์ในการอธิบาย

เนื่องจากมีสี่บิตในจำนวนเต็มจึงสามารถสมมติได้หนึ่งใน 16 ค่า 16 คือสองกำลังสี่หรือ 2 คูณ 2 คูณ 2 คูณ 2 ค่าเหล่านั้นคืออะไร? คำตอบขึ้นอยู่กับว่าจำนวนเต็มนี้เป็น a signed intหรือunsigned int. ด้วยunsigned intค่าจะไม่เป็นลบ ไม่มีสัญลักษณ์ที่เกี่ยวข้องกับค่านี้ นี่คือ 16 ค่าที่เป็นไปได้ของสี่บิตunsigned int:

... และนี่คือ 16 ค่าที่เป็นไปได้ของสี่บิตsigned int:

อย่างที่คุณเห็นสำหรับsigned ints บิตที่สำคัญที่สุดคือ1ถ้าจำนวนนั้นเป็นลบ นั่นคือเหตุผลว่าทำไมsigned intบิตนี้จึงเรียกว่า "บิตเครื่องหมาย"


11
บางทีสิ่งที่ควรค่าแก่การชี้ให้เห็นก็คือนี่เป็นรูปแบบเสริมของทั้งสองซึ่งเป็นที่ยอมรับในปัจจุบันใช้กันอย่างแพร่หลาย นอกจากนี้ยังมีวิธีอื่น ๆ ในการแสดงจำนวนเต็มที่มีการลงนามซึ่งเป็นส่วนเสริมที่โดดเด่นที่สุด
Schedler

แก้ไข. และมาตรฐาน ISO9899 C ไม่ได้กำหนดให้ใช้ส่วนเติมเต็มของหนึ่งหรือสองส่วนเสริม อนุสัญญาอื่นใดที่ใช้งานได้จริงจะได้รับอนุญาต
Bill Evans ที่ Mariposa

1
แม้ว่าส่วนเติมเต็มของ 2 จะไม่จำเป็นต้องใช้ แต่(unsigned)(-1)จำเป็นต้องเป็นค่าที่แสดงได้สูงสุดสำหรับunsigned(ไม่ขึ้นกับการแทนค่าฐานสอง) ซึ่งเป็นจริงเล็กน้อยสำหรับส่วนเสริมของ 2 แต่ไม่ใช่การแสดงอื่น ๆ
rubenvb

3
@BillEvansatMariposa: มาตรฐานกล่าวว่าสำหรับจำนวนเต็มที่ลงนามมีการแสดงที่อนุญาต 3 รายการ ได้แก่ เครื่องหมาย + ขนาดส่วนเสริม 2 ส่วนเติมเต็ม 1 คนอื่น ๆ จะต้องมองไม่เห็นโปรแกรมและถูกมองว่าเป็นหนึ่งใน 3 เหล่านี้
Alexey Frunze

โอเค แต่ภายใต้ประทุน! เกิดอะไรขึ้นจริงๆ! อะไรคือความแตกต่างระหว่างหมายเลขที่มีลายเซ็นและหมายเลขที่ไม่ได้ลงชื่อ! เครื่องจัดการการคำนวณอย่างไร? มันแค่ลบค่าออกจากค่าอื่น? ความแตกต่าง 1111 = 15 และ 1111 = -1?
Mihail Georgescu

19

intและunsigned intเป็นจำนวนเต็มสองประเภทที่แตกต่างกัน ( intนอกจากนี้ยังสามารถเรียกว่าsigned intหรือเพียงแค่signed; unsigned intนอกจากนี้ยังสามารถเรียกว่าunsigned.)

ตามที่ระบุชื่อintเป็นประเภทจำนวนเต็มลงนามและunsigned intเป็นประเภทจำนวนเต็มที่ไม่ได้ลงชื่อ นั่นหมายความว่าintสามารถแทนค่าเชิงลบและunsigned intแสดงได้เฉพาะค่าที่ไม่ใช่ค่าลบเท่านั้น

ภาษา C กำหนดข้อกำหนดบางประการเกี่ยวกับช่วงของประเภทเหล่านี้ ช่วงของintต้องมีอย่างน้อย-32767.. +32767และช่วงของการunsigned intต้องมีอย่างน้อย..0 65535หมายความว่าทั้งสองประเภทต้องมีอย่างน้อย 16 บิต เป็น 32 บิตในหลายระบบหรือแม้แต่ 64 บิตในบางระบบ intโดยทั่วไปจะมีค่าติดลบพิเศษเนื่องจากการแทนค่าสองส่วนที่ใช้โดยระบบที่ทันสมัย

บางทีความแตกต่างที่สำคัญที่สุดคือพฤติกรรมของการลงนามเทียบกับเลขคณิตที่ไม่ได้ลงนาม สำหรับการลงนามintoverflow มีพฤติกรรมที่ไม่ได้กำหนดไว้ เพราะunsigned intไม่มีน้ำล้น ดำเนินการใด ๆ UINT_MAX + 1U == 0Uที่ทำให้ค่านอกช่วงของการตัดประเภทรอบดังนั้นสำหรับตัวอย่างเช่น

ประเภทจำนวนเต็มใด ๆ ทั้งที่ลงชื่อหรือไม่ได้ลงนามจะจำลองช่วงย่อยของชุดจำนวนเต็มทางคณิตศาสตร์ที่ไม่สิ้นสุด ตราบใดที่คุณทำงานกับค่าที่อยู่ในช่วงของประเภททุกอย่างก็ใช้ได้ เมื่อคุณเข้าใกล้ขอบเขตล่างหรือบนของประเภทคุณจะพบกับความไม่ต่อเนื่องและคุณจะได้รับผลลัพธ์ที่ไม่คาดคิด สำหรับการลงนามจำนวนเต็มประเภทปัญหาที่เกิดขึ้นเฉพาะสำหรับลบและบวกค่าขนาดใหญ่มากเกินและINT_MIN INT_MAXสำหรับประเภทจำนวนเต็มไม่ได้ลงนามปัญหาเกิดขึ้นสำหรับค่าบวกขนาดใหญ่มากและที่ศูนย์ นี่อาจเป็นที่มาของข้อบกพร่อง ตัวอย่างเช่นนี่คือการวนซ้ำที่ไม่มีที่สิ้นสุด:

เพราะiเป็นเสมอมากกว่าหรือเท่ากับศูนย์; นั่นเป็นลักษณะของประเภทที่ไม่ได้ลงนาม (ภายในลูปเมื่อiเป็นศูนย์ให้i--ตั้งค่าเป็นUINT_MAX)


14

ในแง่ของคนธรรมดา int ที่ไม่ได้ลงนามคือจำนวนเต็มที่ไม่สามารถเป็นลบได้จึงมีช่วงค่าบวกที่สูงกว่าที่สามารถสันนิษฐานได้ int ที่ลงนามเป็นจำนวนเต็มที่สามารถเป็นลบได้ แต่มีช่วงบวกที่ต่ำกว่าเพื่อแลกกับค่าที่เป็นลบมากขึ้นซึ่งสามารถสันนิษฐานได้


12

บางครั้งเรารู้ล่วงหน้าว่าค่าที่เก็บไว้ในตัวแปรจำนวนเต็มจะเป็นค่าบวกเสมอเมื่อมีการใช้เพื่อนับเฉพาะสิ่งต่างๆเช่น ในกรณีเช่นนี้เราสามารถประกาศให้ตัวแปรไม่ได้ลงนามเช่นเดียวกับในunsigned int num student;. ด้วยการประกาศดังกล่าวช่วงของค่าจำนวนเต็มที่อนุญาต (สำหรับคอมไพเลอร์ 32 บิต) จะเปลี่ยนจากช่วง -2147483648 เป็น +2147483647 เป็นช่วง 0 ถึง 4294967295 ดังนั้นการประกาศจำนวนเต็มที่ไม่ได้ลงนามเกือบสองเท่าของขนาดที่ใหญ่ที่สุดที่เป็นไปได้ มูลค่าที่สามารถถือได้


@ อเล็กซ์ฉันอยู่ระหว่างการแก้ไขคำตอบเมื่อ 10 นาทีที่แล้วและมันก็เหมือนกัน lol
Skuld

0

ในทางปฏิบัติมีความแตกต่างสองประการ:

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

รหัสนี้สามารถระบุจำนวนเต็มโดยใช้เกณฑ์การสั่งซื้อ:


หากสิ่งนี้อธิบายความแตกต่างกับการซื้อขายหนึ่งในจำนวนลบและอีกอัน มันจะช่วยโพสต์นี้ได้มาก
Daniel Jackson

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