เหตุใดจึงต้องใช้ส่วนประกอบสองอย่างแทนเครื่องหมายและขนาดสำหรับหมายเลขที่เซ็นชื่อ


201

ฉันแค่อยากรู้ว่าถ้ามีเหตุผลทำไมเพื่อเป็นตัวแทน -1 ในเลขฐานสองจะใช้สองส่วน: พลิกบิตและเพิ่ม 1?

-1 แทนด้วย 11111111 (ส่วนเสริมสองส่วน) แทน (สำหรับฉันที่เข้าใจง่ายขึ้น) 10000001 ซึ่งเป็นเลขฐานสอง 1 ที่มีบิตแรกเป็นค่าลบ

คำเตือน: ฉันไม่พึ่งพาเลขคณิตเลขฐานสองสำหรับงานของฉัน!


6
FWIW วิธีการ "ใช้งานง่าย" ของคุณในการใช้ sign-bit นั้นถูกใช้ในบางครั้ง - ตัวอย่างเช่นคอมพิวเตอร์ส่วนใหญ่ใช้ sign-bit เมื่อแสดงตัวเลขจุดลอย
Adisak

2
@Adisak มันเรียกว่าขนาดลงนาม
โคลจอห์นสัน

2
ฉันเชื่อมโยงการแสดงสัญลักษณ์และจำนวนเต็มกับเลขจำนวนเต็มเสมอเนื่องจากตัวเลขจุดลอยตัวประกอบด้วยสามองค์ประกอบ: เครื่องหมายเลขชี้กำลังและแม็นทีสสา (มักจะมีเครื่องหมาย '1') แต่ฉันคิดว่ามันง่ายพอที่จะรักษาเลขชี้กำลังและแมนทิสซาให้มีขนาดตราบเท่าที่เรารู้ตัวว่ามันไม่เชิงเส้นอย่างเคร่งครัด
Adisak

ต่อไปนี้เป็นบทความเกี่ยวกับวิธีการจัดเก็บเลขทศนิยมในรูปแบบเลขฐานสองสำหรับผู้ที่สงสัยเกี่ยวกับคำพูดของ @ Adisak
GDP2

เพิ่งเห็นวิดีโอที่ดีอธิบายyoutube.com/watch?v=dHB7jFjESLY
allenlinli

คำตอบ:


333

เสร็จสิ้นเพื่อให้การเพิ่มไม่จำเป็นต้องมีตรรกะพิเศษใด ๆ สำหรับการจัดการกับจำนวนลบ ตรวจสอบบทความเกี่ยวกับวิกิพีเดีย

สมมติว่าคุณมีตัวเลขสองตัวคือ 2 และ -1 ในรูปแบบ "ใช้งานง่าย" ของคุณในการแสดงตัวเลขพวกเขาจะเป็น0010และ1001ตามลำดับ (ฉันติดกับ 4 บิตสำหรับขนาด) ในการเติมเต็มทั้งสองวิธีที่พวกเขามีและ0010 1111ตอนนี้สมมติว่าฉันต้องการเพิ่ม

การเติมเต็มของสองนั้นง่ายมาก คุณเพิ่มหมายเลขตามปกติและบิตนำติดตัวใด ๆ ที่ส่วนท้ายถูกยกเลิก ดังนั้นพวกเขากำลังเพิ่มดังนี้:

  0010
+ 1111
=10001
= 0001 (discard the carry)

0001 คือ 1 ซึ่งเป็นผลลัพธ์ที่คาดหวังของ "2 + (- 1)"

แต่ในวิธี "ใช้งานง่าย" การเพิ่มมีความซับซ้อนมากขึ้น:

  0010
+ 1001
= 1011

-3 คืออะไร การเพิ่มแบบง่ายไม่ทำงานในกรณีนี้ คุณต้องทราบว่าหนึ่งในตัวเลขนั้นเป็นค่าลบและใช้อัลกอริทึมที่ต่างออกไป

สำหรับวิธีการเก็บข้อมูล "ใช้งานง่าย" การลบเป็นการดำเนินการที่แตกต่างจากการเพิ่มซึ่งต้องการการตรวจสอบเพิ่มเติมเกี่ยวกับตัวเลขก่อนที่จะสามารถเพิ่มได้ เนื่องจากคุณต้องการให้การทำงานพื้นฐานที่สุด (การบวกการลบและอื่น ๆ ) นั้นเร็วที่สุดเท่าที่จะเป็นไปได้คุณต้องจัดเก็บตัวเลขในลักษณะที่ช่วยให้คุณใช้อัลกอริธึมที่ง่ายที่สุด

นอกจากนี้ในวิธีการจัดเก็บข้อมูล "ใช้งานง่าย" มีศูนย์สองศูนย์:

0000  "zero"
1000  "negative zero"

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

มีโบนัสอีกวิธีหนึ่งในการจัดเก็บข้อมูลด้วยวิธีนี้และเมื่อคุณต้องการขยายความกว้างของการลงทะเบียนค่าจะถูกเก็บไว้ด้วยความสมบูรณ์ของสองการจัดเก็บหมายเลข 4 บิตในการลงทะเบียน 8 บิตเป็นเรื่องของการทำซ้ำ บิตที่สำคัญที่สุด:

    0001 (one, in four bits)
00000001 (one, in eight bits)
    1110 (negative two, in four bits)
11111110 (negative two, in eight bits)

มันเป็นเพียงเรื่องของการดูที่บิตเครื่องหมายของคำที่เล็กกว่าและทำซ้ำจนกว่ามันจะวางความกว้างของคำที่ใหญ่กว่า

ด้วยวิธีการของคุณคุณจะต้องล้างบิตที่มีอยู่ซึ่งเป็นการดำเนินการเพิ่มเติมนอกเหนือจากการขยาย:

    0001 (one, in four bits)
00000001 (one, in eight bits)
    1010 (negative two, in four bits)
10000010 (negative two, in eight bits)

คุณยังต้องตั้งค่าบิตพิเศษเหล่านั้นอีก 4 บิตในทั้งสองกรณี แต่ในกรณี "ใช้งานง่าย" คุณจะต้องล้างบิตที่ 5 ด้วย นี่เป็นขั้นตอนพิเศษเล็ก ๆ น้อย ๆ หนึ่งในการดำเนินงานพื้นฐานและทั่วไปที่สุดที่มีอยู่ในทุกแอปพลิเคชัน


13
ฉันเห็นด้วย. งานเสริม 2 แต่เรามาถึงที่แรกได้อย่างไร ถ้าสมมติว่าฉันต้องมาถึงสัญกรณ์นี้กระบวนการคิดจะเป็นอย่างไร ฉันคิดว่าการได้มาซึ่งส่วนประกอบของ 2 จะต้องเป็นมากกว่าแค่โชคดีใช่มั้ย
Lazer

1
นอกจากนี้ทำไมไม่มีส่วนเติมเต็ม 2 สำหรับลอย?
Lazer

6
@Lazer ตรวจสอบบทความนี้เพื่อทราบhow we arrived at 2s compliment the first place. cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
Ankit

1
Java มีการลงนามประเภทจำนวนเต็มเท่าที่ฉันทราบดังนั้นมันจึงปฏิบัติต่อมันในการตีความที่สมบูรณ์ของทั้งสอง ในภาษาอื่น ๆ วิธีการที่ได้รับการปฏิบัตินั้นขึ้นอยู่กับว่ารหัสปฏิบัติอย่างไร ไม่มีอะไรจะบอกคุณได้ว่าบล็อกของหน่วยความจำนั้นเป็นเลขจำนวนเต็มที่มีลายเซ็นหรือไม่มีเครื่องหมายหรือเป็นเลขคู่หรือเป็นสตริงหรืออย่างอื่น ข้อมูลดิบเป็นประเภทใดก็ตามที่คุณเลือกที่จะตีความว่าเป็น
Welbog

3
@Suraj ผมขอแนะนำให้ดูที่บทความวิกิพีเดียเติมเต็มสองสำหรับคำตอบทั้งหมด: en.wikipedia.org/wiki/Two%27s_complement คำตอบสั้น ๆ คือ MSB 1บ่งชี้-8และที่เหลืออีกสาม1s บ่งชี้4, 2และตามลำดับเพื่อ1 -8+4+2+1 = -1
Welbog

18

Wikipediaบอกว่ามันทั้งหมด:

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

กล่าวอีกนัยหนึ่งการเพิ่มจะเหมือนกันไม่ว่าตัวเลขจะเป็นลบหรือไม่


ท่านถ้าฉันเขียนถ่าน a = 12; และถ่าน b = 12 ที่ไม่ได้ลงนามเป็นบิตลายพื้นฐานเดียวกันเกิดอะไรขึ้นจริง?
Suraj Jain

ไม่มีอะไรเปลี่ยนแปลงเมื่อเขียนหรืออ่าน ใช้ได้เฉพาะเมื่อบวกหรือลบเท่านั้น
Talespin_Kit

12

แม้ว่าคำถามนี้จะเก่า แต่ให้ฉันใส่ใน 2 เซ็นต์ของฉัน

ก่อนที่ฉันจะอธิบายสิ่งนี้ให้กลับไปสู่พื้นฐาน 2 'complement คือส่วนเติมเต็ม 1 + 1 ทีนี้อะไรคือส่วนเติมเต็มของ 1 และความสำคัญของมันคืออะไร

ผลรวมของจำนวน n บิตใด ๆ และส่วนเติมเต็มของ 1 จะให้ตัวเลขที่เป็นไปได้สูงสุดที่สามารถแทนด้วยบิต n เหล่านั้น ตัวอย่าง:

 0010 (2 in 4 bit system)
+1101 (1's complement of 2)
___________________________
 1111  (the highest number that we can represent by 4 bits)

ตอนนี้จะเกิดอะไรขึ้นถ้าเราพยายามที่จะเพิ่มอีก 1 ผล มันจะส่งผลให้เกิดการล้น

ผลลัพธ์จะ1 0000เป็น 0 (ในขณะที่เรากำลังทำงานกับตัวเลข 4 บิต (1 ด้านซ้ายเป็นโอเวอร์โฟลว์)

ดังนั้น

Any n-bit number + its 1's complement = max n-bit number
Any n-bit number + its 1'complement + 1 = 0 ( as explained above, overflow will occur as we are adding 1 to max n-bit number)

มีคนตัดสินใจที่จะเรียกส่วนประกอบ 1 ของ + 1 เป็น 2'complement ดังนั้นข้อความข้างต้นจะกลายเป็น: หมายเลข n'bit ใด ๆ + ส่วนเติมเต็ม 2 ของมัน = 0 ซึ่งหมายถึงส่วนเติมเต็มของ 2 ของตัวเลข = - (ของจำนวนนั้น)

ทั้งหมดนี้ให้คำถามอีกข้อหนึ่งทำไมเราสามารถใช้เฉพาะ (n-1) ของบิต n เพื่อแทนจำนวนบวกและทำไมบิตที่เหลือมากที่สุด nth แทนสัญลักษณ์ (0 บนบิตซ้ายสุดหมายถึง + ve number และ 1 หมายถึง หมายเลข -ve) เช่นเหตุใดเราจึงใช้เฉพาะ 31 บิตแรกของ int ใน java เพื่อแสดงจำนวนบวกหาก 32 บิตเป็น 1 ก็คือจำนวน -ve

 1100 (lets assume 12 in 4 bit system)
+0100(2's complement of 12)
___________________________

1 0000 (ผลลัพธ์เป็นศูนย์โดยมีการล้น 1 ถือ)

ดังนั้นระบบของ (n + 2'complement ของ n) = 0 ยังคงใช้งานได้ ความกำกวมเพียงอย่างเดียวที่นี่คือการเติมเต็ม 2 ของ 12 คือ 0100 ซึ่งคลุมเครือยังแสดงถึง +8 นอกเหนือจากการเป็นตัวแทน -12 ในระบบเติมเต็ม 2s

ปัญหานี้จะได้รับการแก้ไขหากจำนวนบวกมี 0 เป็นจำนวนบิตซ้ายสุดเสมอ ในกรณีดังกล่าวส่วนประกอบ 2 ของพวกเขาจะมี 1 ส่วนบิตซ้ายสุดเสมอและเราจะไม่มีความกำกวมของบิตชุดเดียวกันซึ่งแสดงถึงหมายเลขประกอบ 2 ของและหมายเลข + ve


1
+1 มันเป็นข้อมูลอย่างไรก็ตามในที่สุดฉันก็ไม่แน่ใจว่าทำไมคุณถึงอยากให้มีบิตที่สำคัญที่สุดเพื่อแสดงว่ามันเป็นจำนวนบวกหรือลบ มันมีปัญหาหลายอย่างเช่น 0 จะมี 2 การแสดง - 0000 (+) และ 1,000 (-) .. นอกจากนี้ยังไม่สามารถทำได้นอกจากนี้การลบและการลบโดยใช้อัลกอริทึมเดียวกัน เมื่อคุณพูดว่า 0100 ปกติแล้วมันคือ +8 และเมื่อคุณพูดเติมเต็มสอง 0100 มันก็คือ -12 ..
hagrawal

8

ส่วนประกอบสองอย่างช่วยให้การบวกและการลบสามารถทำได้ตามปกติ (เช่นคุณบาดเจ็บที่หมายเลขที่ไม่ได้ลงชื่อ) นอกจากนี้ยังป้องกัน -0 (วิธีแยกต่างหากในการแทนค่า 0 ซึ่งจะไม่เท่ากับ 0 ด้วยวิธีการเปรียบเทียบตัวเลขแบบบิตต่อบิต


6

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


5

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

รับค่า 8 บิต a 7 a 6 a 5 a 4 a 3 a 2 a 1 a 0

การตีความเลขฐานสองแบบปกติที่ไม่ได้ลงนามคือ:
2 7 * a 7 + 2 6 * a 6 + 2 5 * a 5 + 2 4 * a 4 + 2 3 * a 3 + 2 2 * a 2 + 2 1 * a 1 + 2 0 * a 0
11111111 = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255

การตีความที่สมบูรณ์ของทั้งสองคือ
-2 7 * a 7 + 2 6 * a 6 + 2 5 * a 5 + 2 4 * a 4 +2 3 * a 3 + 2 2 * a 2 + 2 1 * a 1 + 2 2 0 * a 0
11111111 = -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = -1

ไม่มีบิตอื่นใดที่เปลี่ยนความหมายเลยและการถือเป็น7คือ "ล้น" และไม่คาดว่าจะทำงานดังนั้นการดำเนินการทางคณิตศาสตร์เกือบทั้งหมดจึงทำงานโดยไม่มีการดัดแปลง ขนาดสัญญาณโดยทั่วไปตรวจสอบบิตสัญญาณและใช้ตรรกะที่แตกต่างกัน


4

สองส่วนประกอบช่วยให้สามารถรวมตัวเลขบวกและลบเข้าด้วยกันได้โดยไม่ต้องใช้ตรรกะพิเศษใด ๆ

หากคุณพยายามเพิ่ม 1 และ -1 โดยใช้วิธีของคุณ
10000001 (-1)
+00000001 (1)
คุณจะได้รับ
10000010 (-2)

แต่โดยการใช้ส่วนประกอบสองอย่างเราสามารถเพิ่มได้

11111111 (-1)
+00000001 (1) คุณจะได้รับ
00000000 (0)

เช่นเดียวกับการลบ

นอกจากนี้หากคุณพยายามที่จะลบ 4 จาก 6 (ตัวเลขบวกสองตัว) คุณสามารถเติมเต็ม 2 2 และเพิ่มทั้งสองเข้าด้วยกัน 6 + (-4) = 6 - 4 = 2

ซึ่งหมายความว่าการลบและการเพิ่มทั้งบวกและลบสามารถทำได้ด้วยวงจรเดียวกันในซีพียู


4

หากต้องการขยายคำตอบให้คนอื่น:

ในส่วนที่สอง

  • การเพิ่มเป็นกลไกเดียวกับการเพิ่มจำนวนเต็มบวกธรรมดา
  • การลบจะไม่เปลี่ยนเช่นกัน
  • การคูณด้วย!

ฝ่ายจะต้องมีกลไกที่แตกต่างกัน

ทั้งหมดนี้เป็นจริงเพราะส่วนประกอบสองอย่างนั้นเป็นเพียงแค่เลขคณิตแบบมาตรฐานปกติซึ่งเราเลือกที่จะดูตัวเลขบางส่วนว่าเป็นลบโดยลบโมดูโลออก


ไม่ว่าเพียงคนเดียวไม่ใช่ขยับขยายคูณเหมือนกัน แต่เนื่องจากภาษาระดับสูงส่วนใหญ่ไม่รองรับการเพิ่มจำนวนทวีคูณโดยไม่ต้องใช้ตัวแปลงที่ชัดเจนผลลัพธ์จะเหมือนกันในภาษาเหล่านั้น
phuclv

@ LưuVĩnhPhúc: การขยายการคูณโดยทั่วไปจะเหมือนกัน แต่ผลลัพธ์สำหรับการคูณที่ลงชื่อและที่ไม่ได้ลงชื่อจะรับประกันว่าจะเหมือนกันหากผลลัพธ์นั้นจะพอดีกับช่วงของ int ที่ลงนามแล้ว คอมไพเลอร์บางอย่างเช่น gcc ให้บางอย่างเช่นunsigned mul(unsigned short x, unsigned short y) { return x*y; }[16- บิตสั้น; 32- บิต int] จะสร้างรหัสที่จะทำงานผิดพลาดเป็นครั้งคราวหากผลิตภัณฑ์มีขนาดใหญ่กว่า 2147483647
supercat

2

การอ่านคำตอบสำหรับคำถามนี้ฉันเจอความคิดเห็นนี้ [แก้ไข]

2 ของ 0100 (4) จะเป็น 1100 ตอนนี้ 1100 คือ 12 ถ้าฉันพูดตามปกติ ดังนั้นเมื่อผมพูดปกติ 1100 มันก็คือ 12 แต่เมื่อผมพูดว่าส่วนเสริม 2 ของ 1100 แล้วมันคือ -4? นอกจากนี้ใน Java เมื่อ 1100 (ให้สมมติว่า 4 บิตในตอนนี้) จะถูกเก็บไว้แล้วจะถูกกำหนดอย่างไรถ้ามันเป็น +12 หรือ -4 - hagrawal 2 ก.ค. เวลา 16:53 น

ในความคิดของฉันคำถามที่ถามในความคิดเห็นนี้ค่อนข้างน่าสนใจและดังนั้นฉันต้องการก่อนอื่นให้เรียบเรียงใหม่แล้วให้คำตอบและตัวอย่าง

คำถาม - ระบบจะสร้างวิธีการตีความจำนวนหนึ่งไบต์ที่อยู่ติดกันได้อย่างไร โดยเฉพาะอย่างยิ่งระบบจะสร้างได้อย่างไรว่าลำดับที่กำหนดของไบต์เป็นเลขฐานสองธรรมดาหรือหมายเลขประกอบ 2

คำตอบ - ระบบกำหนดวิธีการตีความลำดับของไบต์ถึงประเภท ประเภทกำหนด

  • จำนวนไบต์ที่ต้องพิจารณา
  • วิธีตีความไบต์เหล่านั้น

ตัวอย่าง - ด้านล่างเราถือว่า

  • charมีความยาว 1 ไบต์
  • shortมีความยาว 2 ไบต์
  • intและfloatมีความยาว 4 ไบต์

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

ครั้งแรกของทั้งหมดที่เรากำหนดอาร์เรย์มี 4 ไบต์และเริ่มต้นทั้งหมดของพวกเขาไปยังหมายเลขไบนารีที่สอดคล้องกับจำนวนฐานสิบหก10111101BD

// BD(hexadecimal) = 10111101 (binary)
unsigned char   l_Just4Bytes[ 4 ]   =   { 0xBD, 0xBD, 0xBD, 0xBD };

จากนั้นเราอ่านเนื้อหาอาเรย์โดยใช้ประเภทที่แตกต่างกัน

unsigned char และ signed char

// 10111101 as a PLAIN BINARY number equals 189
printf( "l_Just4Bytes as unsigned char  -> %hi\n", *( ( unsigned char* )l_Just4Bytes ) );

// 10111101 as a 2'S COMPLEMENT number equals -67
printf( "l_Just4Bytes as signed char    -> %i\n", *( ( signed char* )l_Just4Bytes ) );

unsigned short และ short

// 1011110110111101 as a PLAIN BINARY number equals 48573
printf( "l_Just4Bytes as unsigned short -> %hu\n", *( ( unsigned short* )l_Just4Bytes ) );

// 1011110110111101 as a 2'S COMPLEMENT number equals -16963
printf( "l_Just4Bytes as short          -> %hi\n", *( ( short* )l_Just4Bytes ) );

unsigned int, intและfloat

// 10111101101111011011110110111101 as a PLAIN BINARY number equals 3183328701
printf( "l_Just4Bytes as unsigned int   -> %u\n", *( ( unsigned int* )l_Just4Bytes ) );

// 10111101101111011011110110111101 as a 2'S COMPLEMENT number equals -1111638595
printf( "l_Just4Bytes as int            -> %i\n", *( ( int* )l_Just4Bytes ) );

// 10111101101111011011110110111101 as a IEEE 754 SINGLE-PRECISION number equals -0.092647
printf( "l_Just4Bytes as float          -> %f\n", *( ( float* )l_Just4Bytes ) );

4 ไบต์ใน RAM ( l_Just4Bytes[ 0..3 ]) จะยังคงเหมือนเดิมทุกประการ สิ่งเดียวที่เปลี่ยนแปลงคือวิธีที่เราตีความพวกเขา

อีกครั้งที่เราบอกระบบว่าจะตีความพวกเขาผ่านประเภท

ตัวอย่างข้างต้นเราได้ใช้ประเภทต่อไปนี้เพื่อตีความเนื้อหาของl_Just4Bytesอาร์เรย์

  • unsigned char: 1 ไบต์ในไบนารีธรรมดา
  • signed char: 1 ไบต์ในส่วนเสริม 2
  • unsigned short: 2 ไบต์ในรูปแบบไบนารีธรรมดา
  • short: 2 ไบต์ต่อส่วนที่ 2
  • unsigned int: 4 ไบต์ในรูปแบบไบนารีธรรมดา
  • int: 4 ไบต์ในส่วนเสริม 2
  • float: 4 ไบต์ในรูปแบบความแม่นยำเดี่ยวของ IEEE 754

[แก้ไข] โพสต์นี้ได้รับการแก้ไขหลังจากความคิดเห็นโดยผู้ใช้ 4581301 ขอบคุณที่สละเวลาวางสายที่มีประโยชน์เหล่านี้!


โค้ด Blob นั้นต้องการการแก้ไขเพื่อให้ผู้อ่านไม่ต้องเลื่อนไปมา ดีกว่าความคิดเห็นขนาดใหญ่ที่ด้านบนควรเป็นข้อความเก่าแบบธรรมดาและให้ผู้แสดงภาพดูแลการจัดรูปแบบ คุณควรเพิ่มคำเตือนในบิตใกล้กับจุดสิ้นสุดที่คุณพูดถึงขนาดและการจัดรูปแบบเนื่องจากขนาดไม่คงที่
4581301

+1 สิ่งหนึ่งที่คุณอาจพิจารณาที่จะทำคือ @ mw215 กำลังทำให้คำถาม / คำตอบนี้จับคู่กับรายการ Community Wiki ด้วยตัวของมันเองเพราะมันมีประโยชน์สำหรับผู้ที่อาจสนใจในการตีความ byte แบบดิบนอกบริบทของคณิตศาสตร์เสริมของทั้งสอง
Welbog

ฉันแค่อยากจะรู้ว่าส่วนประกอบของ 2 มักจะตามฉันหมายถึงถ้าฉันมีint x = -4แล้วฉันจะprintf("%d" , x)ตีความได้อย่างไร? นอกจากนี้สิ่งที่เป็นความแตกต่างระหว่างunsigned intและsigned intและ%dและ%u... นี้ได้รับการ bugging ฉันเป็นเวลานานในขณะนี้ .Thanks
Suraj Jain

@Suraj Jain เมื่อใช้intชนิดsignedตัวแก้ไขจะเป็นค่าเริ่มต้น ซึ่งหมายความว่าintและsigned intเป็นประเภทเดียวกัน ดังนั้นทั้งสองคำจำกัดความint i = -4;และsigned int i = -4;มีความหมายเหมือนกัน
mw215

@Suraj Jain ระบบกำหนดวิธีการตีความลำดับของไบต์ผ่านประเภท ประเภทกำหนด: จำนวนไบต์ที่ต้องพิจารณาและวิธีการไบต์เหล่านั้นจะต้องมีการตีความ An intคือ 4 ไบต์ในส่วนเสริมของ 2และunsigned intเป็น 4 ไบต์ในรูปแบบไบนารีธรรมดา (ตรวจสอบขนาดจริงประเภทในระบบของคุณโดยใช้sizeofผู้ประกอบการ)
mw215

1

คุณสามารถดู Professor Jerry Cain จาก Stanford อธิบายส่วนประกอบทั้งสองได้ในการบรรยายครั้งที่สอง (คำอธิบายเกี่ยวกับส่วนประกอบ 2 เริ่มประมาณ 13:00 น.) ในชุดการบรรยายที่เรียกว่า Programming Paradigms พร้อมให้ชมจากช่อง YouTube ของ Standford นี่คือการเชื่อมโยงไปบรรยายชุดนี้: http://www.youtube.com/view_play_list?p=9D558D49CA734A02


0

ส่วนประกอบสองอย่างนั้นถูกนำมาใช้เพราะมันง่ายกว่าที่จะนำไปใช้ในวงจรและไม่อนุญาตให้มีศูนย์ลบ

หากมีบิต x ส่วนประกอบทั้งสองจะอยู่ในช่วงตั้งแต่ + (2 ^ x / 2 + 1) ถึง - (2 ^ x / 2) ส่วนประกอบหนึ่งจะเริ่มต้นจาก + (2 ^ x / 2) ถึง - (2 ^ x / 2) แต่จะอนุญาตให้ศูนย์ลบ (0000 เท่ากับ 1,000 ในระบบประกอบของ 4 บิต 1)


0

ความตั้งใจของคุณไม่ใช่การย้อนกลับบิตของเลขฐานสองของคุณทั้งหมด ที่จริงแล้วมันคือการลบแต่ละหลักจาก 1 มันเป็นเรื่องบังเอิญที่โชคดีที่การลบ 1 จาก 1 ผลลัพธ์ใน 0 และลบ 0 จาก 1 ผลลัพธ์ใน 1 ดังนั้นการพลิกบิตจึงเป็นการลบอย่างมีประสิทธิภาพ

แต่ทำไมคุณถึงค้นหาความแตกต่างของแต่ละหลักจาก 1? คุณไม่ได้ เจตนาที่แท้จริงของคุณคือการคำนวณความแตกต่างของเลขฐานสองที่ได้รับจากเลขฐานสองอื่นซึ่งมีจำนวนหลักเดียวกัน แต่มีเพียง 1 เท่านั้น ตัวอย่างเช่นถ้าหมายเลขของคุณคือ 10110001 เมื่อคุณพลิกบิตทั้งหมดคุณจะคำนวณได้อย่างมีประสิทธิภาพ (11111111 - 10110001)

สิ่งนี้จะอธิบายขั้นตอนแรกในการคำนวณของการเติมเต็มสอง ทีนี้ลองมารวมขั้นตอนที่สอง - เพิ่ม 1 - ลงในภาพด้วย

เพิ่ม 1 ไปยังสมการฐานสองข้างต้น:

11111111 - 10110001 + 1

คุณได้อะไร นี้:

100000000 - 10110001

นี่คือสมการสุดท้าย และด้วยการดำเนินการสองขั้นตอนที่คุณพยายามค้นหาสิ่งนี้ความแตกต่างสุดท้าย: เลขฐานสองถูกลบออกจากเลขฐานสองอื่นที่มีตัวเลขพิเศษหนึ่งหลักและมีเลขศูนย์ยกเว้นที่ตำแหน่งบิตที่มีความหมายมากที่สุด

แต่ทำไมเราถึง hankerin หลังจากความแตกต่างนี้จริงๆ ดีจากที่นี่ผมคิดว่ามันจะดีกว่าถ้าคุณอ่านบทความวิกิพีเดีย


0

เราดำเนินการเพิ่มเฉพาะสำหรับทั้งการบวกและการลบ เราเพิ่มตัวถูกดำเนินการที่สองในตัวถูกดำเนินการแรกสำหรับการเพิ่ม สำหรับการลบเราเพิ่มส่วนเสริม 2 ของตัวถูกดำเนินการที่สองไปยังตัวถูกดำเนินการแรก

ด้วยการเป็นตัวแทนของส่วนเสริม 2 เราไม่จำเป็นต้องใช้อุปกรณ์ดิจิตอลแยกต่างหากสำหรับการลบ - ใช้เฉพาะอุปกรณ์เสริมและอุปกรณ์เสริมเท่านั้น


0

ควรทราบว่าสำหรับเครื่องเพิ่มบางรุ่นก่อนวันคอมพิวเตอร์จะทำการลบโดยให้ผู้ปฏิบัติงานป้อนค่าโดยใช้ชุดสีที่ต่างกันของตำนานในแต่ละคีย์ (ดังนั้นแต่ละคีย์จะป้อนเก้าลบด้วยจำนวนที่จะเป็น ลบออก) และกดปุ่มพิเศษจะถือว่ามีผลในการคำนวณ ดังนั้นบนเครื่องหกหลักเพื่อลบ 1234 จากค่าตัวดำเนินการจะกดแป้นที่ปกติจะระบุว่า "998,765" และกดปุ่มเพื่อเพิ่มค่านั้นบวกกับการคำนวณที่กำลังดำเนินอยู่ เลขคณิตประกอบสองของเป็นเพียงเลขฐานสองของเลขคณิตสิบส่วนเสริมก่อนหน้านี้


0

ข้อดีของการลบโดยใช้วิธีการเสริมคือการลด
ความซับซ้อนของฮาร์ดแวร์ไม่จำเป็นต้องใช้วงจรดิจิตอลที่แตกต่างกันสำหรับการบวกและการลบการบวกและการลบทั้งสองจะดำเนินการโดย adder เท่านั้น


0

ประโยชน์ที่สำคัญของการเป็นตัวแทน two's-เติมเต็มซึ่งยังไม่ได้รับการกล่าวถึงที่นี่เป็นที่บิตล่างของผลรวม two's-เติมเต็มความแตกต่างหรือผลิตภัณฑ์จะขึ้นอยู่เฉพาะเมื่อบิตที่สอดคล้องกันของตัวถูกดำเนิน เหตุผลที่ค่า 8 บิตที่ลงนามสำหรับ -1 คือการ11111111ลบจำนวนเต็มใด ๆที่มี 8 บิตต่ำสุด00000001จากจำนวนเต็มอื่น ๆ ที่มีบิตต่ำสุด 8 บิต0000000จะให้ผลเป็นจำนวนเต็มที่มี 8 บิตต่ำสุด11111111. ในทางคณิตศาสตร์ค่า -1 จะเป็นสตริงที่ไม่มีที่สิ้นสุดของ 1 แต่ค่าทั้งหมดที่อยู่ในช่วงของประเภทจำนวนเต็มจะเป็น 1 หรือ 0 ทั้งหมดที่ผ่านมาในบางจุดดังนั้นจึงสะดวกสำหรับคอมพิวเตอร์ที่จะ "ลงชื่อขยาย" บิตที่สำคัญที่สุดของตัวเลขราวกับว่ามันแทนจำนวนอนันต์ของ 1 หรือ 0

Two's-complement เป็นเพียงการแสดงหมายเลขลงนามเท่านั้นที่ทำงานได้ดีเมื่อจัดการกับชนิดที่มีขนาดใหญ่กว่าขนาดของเครื่องคำไบนารีเนื่องจากเมื่อทำการบวกหรือลบรหัสสามารถดึงอันต่ำสุดของแต่ละตัวถูกดำเนินการคำนวณอันต่ำสุดของ ผลลัพธ์และเก็บไว้แล้วโหลดอันถัดไปของแต่ละตัวถูกดำเนินการคำนวณอันถัดไปของผลลัพธ์และเก็บไว้เป็นต้นดังนั้นแม้แต่ตัวประมวลผลที่ต้องการการเพิ่มและการลบทั้งหมดเพื่อผ่านการลงทะเบียน 8 บิตเดียว สามารถจัดการกับหมายเลขที่ลงชื่อแบบ 32- บิตได้อย่างมีประสิทธิภาพ (ช้ากว่าการลงทะเบียนแบบ 32 บิตแน่นอน แต่ยังสามารถใช้งานได้)

เมื่อใช้การรับรองที่ลงนามอื่น ๆ ที่ได้รับอนุญาตโดยมาตรฐาน C ผลของบิตทุกบิตอาจได้รับผลกระทบจากบิตของตัวถูกดำเนินการทำให้จำเป็นต้องถือค่าทั้งหมดในการลงทะเบียนทันทีหรืออย่างอื่นตามด้วยการคำนวณพิเศษ ขั้นตอนที่อย่างน้อยก็ในบางกรณีจำเป็นต้องมีการอ่านการแก้ไขและการเขียนผลลัพธ์แต่ละอันใหม่


โปรดจัดรูปแบบคำตอบของคุณในย่อหน้าและทำเครื่องหมายรหัสเป็นรหัสมันจะสามารถอ่านได้มากขึ้นและคุณจะได้รับ upvote
Suraj Jain

@SurajJain: ดีกว่าเหรอ?
supercat

ใช่ดีกว่าที่เคยเป็นมาฉันต้องการถามคุณสิ่งหนึ่งความแตกต่างระหว่าง char char ที่ลงนาม = 1 และ char ที่ไม่ได้ลงนาม a = 1 เป็นอย่างไรพวกเขาแสดงในหน่วยความจำอย่างไร
Suraj Jain

@SurajJain: บนระบบสองระบบที่ "char" มีขนาดเล็กกว่า "int" [เช่นระบบส่วนใหญ่] ประเภท char ที่ลงชื่อและไม่ได้ลงชื่อจะทำงานเหมือนกันยกเว้นประเภทที่ลงชื่อจะถูกขยายเมื่อลงชื่ออ่านและประเภทที่ไม่ได้ลงชื่อ เคยชิน. บนระบบดังกล่าวการจัดเก็บค่า 194 หรือ -62 ลงในถ่านที่ลงนามแล้วจะเขียนรูปแบบบิตเดียวกับการเก็บ 194 หรือ -62 ลงในถ่านที่ไม่ได้ลงชื่อ (เช่น 11000010) การอ่านรูปแบบบิตนั้นจากถ่านที่ลงนามแล้วจะให้ -62 และการอ่านจากถ่านที่ไม่ได้ลงนามจะให้ผล 194
Supercat

หมายถึงการขยายสัญญาณ?
Suraj Jain

0

การเป็นตัวแทนมีหลายประเภท ได้แก่ :

  1. การแทนตัวเลขที่ไม่ได้ลงนาม
  2. การแสดงหมายเลขที่ลงนามแล้ว
  3. การเป็นตัวแทนของคน ๆ หนึ่ง
  4. การเป็นตัวแทนของสองอย่างสมบูรณ์

แสดงตัวเลขที่ไม่ได้ลงนามใช้เพื่อแสดงตัวเลขที่เป็นบวกเท่านั้น

- การแทนตัวเลขที่ลงนามใช้เพื่อแทนค่าบวกรวมถึงจำนวนลบ ในการเป็นตัวแทนตัวเลขลงนามบิต MSB หมายถึงบิตสัญญาณและบิตที่เหลือหมายถึงจำนวน เมื่อ MSB เป็น 0 หมายถึงจำนวนเป็นบวกและเมื่อ MSB เป็น 1 หมายถึงจำนวนเป็นลบ

ปัญหาเกี่ยวกับการแสดงตัวเลขที่ลงนามคือมีสองค่าสำหรับ 0

ปัญหาเกี่ยวกับการแสดงส่วนประกอบหนึ่งของคือว่ามีสองค่าสำหรับ 0

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

แหล่งที่มา: เหตุใดจึงมีการจัดเก็บตัวเลขติดลบในรูปแบบเสริมของสองไบต์ไบต์กิกะไบต์


-1

คำตอบที่น่าพอใจอย่างหนึ่งของเหตุผลที่ Two2's Complement ใช้แทนตัวเลขลบมากกว่าระบบ Complement ของ One ก็คือว่าระบบ Complement ของ Two แก้ปัญหาของการแทนหลาย ๆ 0และความต้องการend-around-carryซึ่งมีอยู่ในระบบที่สมบูรณ์ของ One หมายเลข

สำหรับข้อมูลเพิ่มเติมโปรดไปที่https://en.wikipedia.org/wiki/Signed_number_representations

สำหรับ End-around-carry เยี่ยมชม https://en.wikipedia.org/wiki/End-around_carry


ที่จริงถ้าคุณมีจุดทศนิยมและชัดเจนเกี่ยวกับสิ่งที่บิตทั้งหมด: "0..0000.1111..1" หมายความว่าบิตทั้งหมดที่ยังไม่ได้คะแนนซ้ายสุดคือ 0 และบิตขวาที่ไม่ได้จัดอันดับคือ 1 ดังนั้น "..1" หมายถึงการพกพาถูกเรียกขึ้นมา ดังนั้นมัน (โดยกลไก) "0.0001.0000..0" หมายความว่า "1..1111.1111..1" เท่ากับศูนย์! นี่ก็หมายความว่าหากต้องการลบจำนวนเต็มคุณจะต้องทำการพลิกบิต แต่ตอนนี้มันใช้กับเศษส่วนที่สามารถแทนได้
Rob
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.