ทำไม ~ 2 ถึง -3 วิธีการ~
ทำงานของผู้ประกอบการ?
ทำไม ~ 2 ถึง -3 วิธีการ~
ทำงานของผู้ประกอบการ?
คำตอบ:
โปรดจำไว้ว่าตัวเลขลบจะถูกจัดเก็บเป็นส่วนเติมเต็มของคู่ที่เป็นบวก ดังตัวอย่างต่อไปนี้เป็นตัวแทนของ -2 ในส่วนเติมเต็มของสอง: (8 บิต)
1111 1110
วิธีที่คุณจะได้รับคือการใช้เลขฐานสองแทนการเติมเต็ม (เติมบิตทั้งหมด) และเพิ่มเข้าไป สองเริ่มเป็น 0000 0010 และโดยการตัดบิตเราจะได้รับ 1111 1101 การเพิ่มหนึ่งทำให้เราได้ผลลัพธ์ข้างต้น บิตแรกคือเครื่องหมายบิตซึ่งหมายถึงค่าลบ
ลองดูวิธีที่เราได้ ~ 2 = -3:
นี่คือสองอีกครั้ง:
0000 0010
เพียงแค่พลิกบิตทั้งหมดและเราจะได้รับ:
1111 1101
ทีนี้, -3 มีลักษณะอย่างไรในสองส่วนเติมเต็ม? เริ่มต้นด้วยค่าบวก 3: 0000 0011 พลิกบิตทั้งหมดเป็น 1111 1100 และเพิ่มหนึ่งค่าเป็นค่าลบ (-3), 1111 1101
ดังนั้นถ้าคุณสลับบิตใน 2 คุณจะได้การแทนสมบูรณ์ของทั้งสองเป็น -3
~
พลิกบิตในค่า
ทำไม~2
จะ-3
มีการทำกับบิตว่าตัวเลขจะเป็นตัวแทนของ ตัวเลขจะแสดงเป็นส่วนเติมเต็มสอง
ดังนั้น 2 คือค่าไบนารี
00000010
และ ~ 2 พลิกบิตดังนั้นค่าตอนนี้:
11111101
ซึ่งเป็นตัวแทนไบนารีของ -3
ตามที่คนอื่นพูดถึง~
เพียงแค่พลิกบิต (เปลี่ยนหนึ่งเป็นศูนย์และศูนย์ถึงหนึ่ง) และเนื่องจากใช้ส่วนประกอบสองอย่างคุณจะได้รับผลลัพธ์ที่คุณเห็น
สิ่งหนึ่งที่จะเพิ่มคือเหตุผลที่ใช้ส่วนประกอบสองอย่างนี้เพื่อให้การดำเนินการเกี่ยวกับจำนวนลบจะเหมือนกับในจำนวนบวก ให้คิดว่า-3
เป็นตัวเลขที่3
ควรเพิ่มเพื่อให้ได้ศูนย์และคุณจะเห็นว่าตัวเลขนี้คือ1101
โปรดจำไว้ว่าการบวกเลขฐานสองนั้นเหมือนกับโรงเรียนประถม (ทศนิยม) นอกจากนี้เพียงคุณมีหนึ่งเมื่อคุณได้รับสองมากกว่า 10 .
1101 +
0011 // 3
=
10000
=
0000 // lose carry bit because integers have a constant number of bits.
ดังนั้น1101
คือ-3
พลิกบิตที่คุณได้รับ0010
ซึ่งเป็นสอง
การดำเนินการนี้เป็นส่วนเสริมไม่ใช่การปฏิเสธ
พิจารณาว่า ~ 0 = -1 และทำงานจากที่นั่น
อัลกอริทึมสำหรับการปฏิเสธคือ "ส่วนเพิ่ม"
เธอรู้รึเปล่า? นอกจากนี้ยังมี "ส่วนเสริม" ที่หมายเลขผกผันมีความสมมาตรและมีทั้ง 0 และ a -0
ฉันรู้ว่าคำตอบสำหรับคำถามนี้โพสต์มานาน แต่ฉันต้องการแบ่งปันคำตอบของฉันเหมือนกัน
สำหรับการหาส่วนประกอบของตัวเลขอันดับแรกให้หาเลขฐานสองที่เทียบเท่ากัน ที่นี่ตัวเลขทศนิยม2
จะแสดงเป็น0000 0010
ในรูปแบบไบนารี ตอนนี้รับส่วนเสริมของมันด้วยการแปลงกลับ (หมุน 1 ทั้งหมดเป็น 0 และ 0 ทั้งหมดเป็น 1) ตัวเลขทั้งหมดของการแทนเลขฐานสองของมันซึ่งจะส่งผลให้:
0000 0010 → 1111 1101
นี่คือส่วนเติมเต็มของเลขทศนิยม 2 และตั้งแต่บิตแรกนั่นคือเครื่องหมายบิตคือ 1 ในเลขฐานสองหมายความว่าเครื่องหมายเป็นลบสำหรับหมายเลขที่เก็บไว้ (ที่นี่จำนวนที่อ้างถึงไม่ใช่ 2 แต่เป็นส่วนประกอบที่สมบูรณ์ของ 2)
ตอนนี้เนื่องจากตัวเลขจะถูกเก็บไว้เป็นส่วนเติมเต็มของ 2 (นำส่วนบวกของตัวเลขบวกหนึ่ง) มาแสดงแทนเลขฐานสองนี้1111 1101
เป็นทศนิยมก่อนอื่นเราต้องหาส่วนประกอบของ 2 ซึ่งจะเป็น:
1111 1101 → 0000 0010 + 1 → 0000 0011
นี่คือส่วนประกอบ 2 ของ แสดงทศนิยมของเลขฐานสองที่เป็น0000 0011
และเนื่องจากบิตเครื่องหมายเป็นหนึ่งดังกล่าวข้างต้นจึงเป็นคำตอบที่ทำให้เกิดเป็น3
-3
คำแนะนำ:หากคุณอ่านขั้นตอนนี้อย่างระมัดระวังคุณจะสังเกตได้ว่าผลลัพธ์สำหรับผู้ประกอบการที่สมบูรณ์นั้นจริง ๆ แล้วจำนวน (ตัวถูกดำเนินการ - ซึ่งใช้ตัวดำเนินการนี้) บวกกับเครื่องหมายลบ คุณสามารถลองกับตัวเลขอื่น ๆ ได้เช่นกัน
add, flip, add
แล้ว 0010
-> 0011
-> 1100
->1101
0010
1101
0010
NOT 0 = 1
NOT 1 = 0
ในระบบสี่บิตNOT 0011
(3) = 1100
(12 ไม่ได้ลงนาม -4 ลงนาม) จากสิ่งที่ฉันเข้าใจส่วนประกอบของสองถูกกำหนดเป็น(NOT n) + 1
และใช้เพื่อค้นหาค่าลบของตัวเลขโดยไม่คำนึงถึงจำนวนบิต ดังนั้น2c(5) = -5
. ดูสิตอนนี้มันสมเหตุสมผลดี ตราบใดที่คุณเรียกการดำเนินการนี้มันคืออะไร: bitwise ไม่
int a = 4; System.out.println (~ ก); ผลลัพธ์จะเป็น: -5
'~' ของจำนวนเต็มใด ๆ ใน java หมายถึงส่วนเติมเต็มของหมายเลข 1 เช่นฉันกำลัง ~ 4 ซึ่งหมายถึงในการเป็นตัวแทนไบนารี 0100 ครั้งแรกความยาวของจำนวนเต็มสี่ไบต์คือ 4 * 8 (8 บิตสำหรับ 1 ไบต์) = 32 ดังนั้นในหน่วยความจำระบบ 4 จะแสดงเป็น 0000 0000 0000 0000 0000 0000 0000 0100 ตอนนี้ ~ โอเปอเรเตอร์จะแสดงส่วนเสริม 1 ของเลขฐานสองด้านบน
เช่น 1111 1111 1111 1111 1111 1111 1111 1011-> 1 เติมเต็มบิตที่สำคัญที่สุดแสดงถึงสัญญาณของ no (ทั้ง - หรือ +) ถ้ามันเป็น 1 แล้วเครื่องหมายคือ '-' ถ้ามันเป็น 0 แล้วลงชื่อเป็น '+' ตาม ผลลัพธ์ของเรานี้คือจำนวนลบในจาวาตัวเลขลบจะถูกจัดเก็บในรูปแบบของ 2 ผลที่ได้มาเราต้องแปลงให้เป็น 2 ส่วน ทั้งหมดจะกลายเป็นศูนย์ยกเว้นบิตที่สำคัญที่สุด 1 (ซึ่งเป็นเครื่องหมายของเราแทนจำนวนซึ่งหมายความว่าเหลือ 31 บิต 1111 1111 1111 1111 1111 1111 1111 1111 1011 (ผลที่ได้มาจากผู้ประกอบการ ~) 1,000 0000 0000 0000 0000 0000 0000 0100 (ส่วนประกอบ 1)
1,000 0000 0000 0000 0000 0000 0000 0101 ตอนนี้ผลลัพธ์คือ -5 ลองดูลิงค์นี้สำหรับวิดีโอ <[ตัวดำเนินการ bit ที่ชาญฉลาดในภาษาจาวา] https://youtu.be/w4pJ4cGWe9Y
เพียง ...........
ในฐานะที่เป็น 2 ส่วนประกอบของจำนวนใด ๆ ที่เราสามารถคำนวณได้โดย inverting 1s ถึง 0 ทั้งหมดและในทางกลับกันมากกว่าที่เราเพิ่ม 1 ลงไป ..
ที่นี่ N = ~ N ให้ผลลัพธ์ - (N + 1) เสมอ เนื่องจากระบบจัดเก็บข้อมูลในรูปแบบของส่วนประกอบ 2 ซึ่งหมายความว่าจะเก็บ ~ N เช่นนี้
~N = -(~(~N)+1) =-(N+1).
ตัวอย่างเช่น::
N = 10 = 1010
Than ~N = 0101
so ~(~N) = 1010
so ~(~N) +1 = 1011
ตอนนี้จุดมาจากที่ลบมา ความคิดเห็นของฉันสมมติว่าเรามีการลงทะเบียน 32 บิตซึ่งหมายถึง 2 ^ 31 -1 บิตที่เกี่ยวข้องในการดำเนินการและส่วนที่เหลือหนึ่งบิตซึ่งการเปลี่ยนแปลงในการคำนวณก่อนหน้านี้ (ส่วนประกอบ) เก็บไว้เป็นบิตสัญญาณซึ่งเป็น 1 ปกติ และเราได้ผลลัพธ์เป็น ~ 10 = -11
~ (-11) = 10;
ด้านบนเป็นจริงถ้า printf ("% d", ~ 0); เราได้รับผล: -1;
แต่ printf ("% u", ~ 0) มากกว่าผลลัพธ์: 4294967295 บนเครื่อง 32 บิต
ตัวดำเนินการเสริม Bitwise (~) เป็นตัวดำเนินการเอก
มันทำงานตามวิธีการดังต่อไปนี้
ก่อนอื่นมันจะแปลงจำนวนทศนิยมที่กำหนดให้ เป็นค่าเลขฐานสองที่สอดคล้องกันในกรณีที่ 2 จะเป็นการแปลง 2 ถึง 0000 0010 (เป็นเลขฐานสอง 8 บิต)
จากนั้นมันจะแปลง 1 ทั้งหมดในจำนวนเป็น 0 และศูนย์ทั้งหมดเป็น 1 จากนั้นตัวเลขจะกลายเป็น 1111 1101
นั่นคือส่วนประกอบ 2 ของ -3
เพื่อหาค่าที่ไม่ได้ลงนามโดยใช้ส่วนประกอบเช่นเพียงแปลง 1111 1101 เป็นทศนิยม (= 4294967293) เราสามารถใช้% u ระหว่างการพิมพ์ได้
ฉันคิดว่าสำหรับคนส่วนใหญ่ความสับสนนั้นมาจากความแตกต่างระหว่างเลขฐานสิบและเลขฐานสองที่เซ็นชื่อดังนั้นให้ชี้แจงก่อน:
สำหรับโลกเลขฐานสิบของมนุษย์: 01 หมายถึง 1, -01 หมายถึง -1, สำหรับโลกฐานสองของคอมพิวเตอร์: 101 หมายถึง 5 หากไม่ได้ลงนาม 101 หมายถึง (-4 + 1) ถ้าลงชื่อในขณะที่ตัวเลขที่เซ็นชื่ออยู่ที่ตำแหน่ง x | x
ดังนั้นบิตที่ 2 ของพลิก = ~ 2 = ~ (010) = 101 = -4 + 1 = -3 ความสับสนเกิดขึ้นจากการผสมผลลัพธ์ที่ลงนาม (101 = -3) และผลลัพธ์ที่ยังไม่ได้อ่าน (101 = 5)
tl; dr ~
พลิกบิต เป็นผลให้การเปลี่ยนแปลงสัญญาณ ~2
เป็นจำนวนลบ ( 0b..101
) เพื่อส่งออกจำนวนลบruby
พิมพ์-
แล้วเติมเต็มสองของ:~2
-(~~2 + 1) == -(2 + 1) == 3
ตัวเลขที่เป็นบวกจะถูกส่งออกตามที่เป็นอยู่
มีค่าภายในและแสดงสตริง สำหรับจำนวนเต็มบวกโดยทั่วไปแล้วพวกเขาตรง:
irb(main):001:0> '%i' % 2
=> "2"
irb(main):002:0> 2
=> 2
หลังถูกเทียบเท่ากับ:
irb(main):003:0> 2.to_s
"2"
~
พลิกบิตของค่าภายใน เป็น2
เป็น สองจุด ( ) แทนจำนวนอนันต์ของ's เนื่องจากบิตที่สำคัญที่สุด (MSB) ของผลลัพธ์คือผลลัพธ์จึงเป็นจำนวนลบ ( ) หากต้องการส่งออกจำนวนพิมพ์เชิงลบจากนั้นให้ส่วนประกอบทั้งสองของค่าภายใน เติมเต็มทั้งสองจะถูกคำนวณโดยการพลิกบิตแล้วเพิ่ม ส่วนประกอบที่สองของมี เช่นนี้:0b010
~2
0b..101
..
1
1
(~2).negative? == true
ruby
-
1
0b..101
3
irb(main):005:0> '%b' % 2
=> "10"
irb(main):006:0> '%b' % ~2
=> "..101"
irb(main):007:0> ~2
=> -3
เมื่อต้องการหาผลรวมมันจะพลิกบิตซึ่งเปลี่ยนเครื่องหมาย หากต้องการส่งออกจำนวนลบจะพิมพ์-
จากนั้น~~2 + 1
( ~~2 == 2
)
เหตุผลที่ruby
ส่งออกตัวเลขติดลบเช่นนั้นเป็นเพราะมันปฏิบัติต่อค่าที่เก็บไว้เป็นส่วนเติมเต็มของค่าสัมบูรณ์ ในคำอื่น ๆ 0b..101
สิ่งที่เก็บไว้ x
มันเป็นจำนวนลบและเป็นเช่นนั้นเป็นส่วนประกอบที่สองของค่าบางอย่าง ในการค้นหาx
มันเป็นการรวมกันของ0b..101
สองอย่าง x
ซึ่งเป็นส่วนประกอบที่สองของส่วนประกอบที่สองของ อันไหนx
(เช่น~(~2 + 1) + 1 == 2
)
ในกรณีที่คุณใช้~
กับจำนวนลบมันจะพลิกบิต (ซึ่งยังคงเปลี่ยนเครื่องหมาย):
irb(main):008:0> '%b' % -3
=> "..101"
irb(main):009:0> '%b' % ~-3
=> "10"
irb(main):010:0> ~-3
=> 2
สิ่งที่สับสนมากกว่านั้นคือ~0xffffff00 != 0xff
(หรือค่าอื่น ๆ ที่มี MSB เท่ากับ1
) ~0xf0 != 0x0f
ลองลดความซับซ้อนของมันบิต: นั่นเป็นเพราะมันถือว่า0xf0
เป็นจำนวนบวก ซึ่งทำให้รู้สึกจริง ดังนั้น~0xf0 == 0x..f0f
. ผลลัพธ์คือจำนวนลบ ส่วนประกอบที่สองของมี0x..f0f
0xf1
ดังนั้น:
irb(main):011:0> '%x' % ~0xf0
=> "..f0f"
irb(main):012:0> (~0xf0).to_s(16)
=> "-f1"
ในกรณีที่คุณจะไม่ใช้ตัวดำเนินการระดับบิตกับผลลัพธ์คุณสามารถพิจารณา~
เป็นตัว-x - 1
ดำเนินการ:
irb(main):018:0> -2 - 1
=> -3
irb(main):019:0> --3 - 1
=> 2
แต่นั่นก็เป็นเนื้อหาที่ไม่ค่อยได้ใช้
ตัวอย่างการพูด Let 's คุณได้รับ 8 บิต (สำหรับความเรียบง่าย) netmask และคุณต้องการในการคำนวณจำนวนของ0
's คุณสามารถคำนวณได้โดยการพลิกบิตและการโทรbit_length
( 0x0f.bit_length == 4
) แต่~0xf0 == 0x..f0f
ดังนั้นเราต้องตัดบิตที่ไม่จำเป็นออก:
irb(main):014:0> '%x' % (~0xf0 & 0xff)
=> "f"
irb(main):015:0> (~0xf0 & 0xff).bit_length
=> 4
หรือคุณสามารถใช้ตัวดำเนินการ XOR ( ^
):
irb(main):016:0> i = 0xf0
irb(main):017:0> '%x' % i ^ ((1 << i.bit_length) - 1)
=> "f"
ก่อนอื่นเราต้องแยกตัวเลขที่กำหนดให้เป็นเลขฐานสองของมันแล้วย้อนกลับโดยการเพิ่มที่เลขฐานสองสุดท้ายหลังจากการดำเนินการนี้เราจะต้องให้เครื่องหมายตรงข้ามกับตัวเลขก่อนหน้านี้ที่เรากำลังหาผู้ร้องเรียน ~ 2 = -3 คำอธิบาย : 2s รูปแบบไบนารีคือ 00000010 เปลี่ยนเป็น 11111101 นี่คือส่วนประกอบที่สมบูรณ์จากนั้นจึง 00000010 + 1 = 00000011 ซึ่งเป็นรูปแบบไบนารีของสามและด้วย -sign Ie, -3
ตัวดำเนินการ bit-wise เป็นตัวดำเนินการเอกที่ทำงานบนวิธีการเซ็นชื่อและขนาดตามประสบการณ์และความรู้ของฉัน
ตัวอย่างเช่น ~ 2 จะส่งผลให้ -3
นี่เป็นเพราะตัวดำเนินการ bit-wise จะแสดงตัวเลขในเครื่องหมายและขนาดซึ่งเป็น 0000 0010 (ตัวดำเนินการ 8 บิต) ก่อนซึ่ง MSB เป็นบิตสัญญาณ
จากนั้นต่อมามันก็หาจำนวนลบของ 2 ซึ่งก็คือ -2
-2 แสดงเป็น 1,000 0010 (ตัวดำเนินการ 8 บิต) ในเครื่องหมายและขนาด
ต่อมามันเพิ่ม 1 เข้ากับ LSB (1,000 0010 + 1) ซึ่งให้คุณ 1,000 0011
ซึ่งคือ -3
Javascript tilde (~) รวมค่าที่กำหนดเข้ากับส่วนเสริม - บิตทั้งหมดกลับด้าน นั่นคือตัวหนอนทั้งหมด มันไม่ได้ลงนามความเห็น มันไม่ได้เพิ่มหรือลบปริมาณใด ๆ
0 -> 1
1 -> 0
...in every bit position [0...integer nbr of bits - 1]
สำหรับโปรเซสเซอร์เดสก์ท็อปมาตรฐานที่ใช้ภาษาระดับสูงเช่น JavaScript เลขฐานสองที่ลงนามเป็นพื้นฐานที่สุด แต่จำไว้เสมอว่าไม่ใช่ประเภทเดียว บิตที่ระดับ CPU อาจมีการตีความตามปัจจัยหลายประการ ที่ระดับ 'รหัส' ในกรณีนี้ JavaScript พวกเขาถูกตีความว่าเป็นจำนวนเต็ม 32 บิตที่มีลายเซ็นตามคำจำกัดความ (ปล่อยให้ลอยออกจากสิ่งนี้) คิดว่ามันเป็นควอนตัม 32 บิตเหล่านั้นเป็นตัวแทนของค่าที่เป็นไปได้มากมายในครั้งเดียว ขึ้นอยู่กับเลนส์แปลงที่คุณมองผ่าน
JavaScript Tilde operation (1's complement)
BASE2 lens
~0001 -> 1110 - end result of ~ bitwise operation
BASE10 Signed lens (typical JS implementation)
~1 -> -2
BASE10 Unsigned lens
~1 -> 14
ทั้งหมดที่กล่าวมาเป็นจริงในเวลาเดียวกัน
การกระทำโดยทั่วไปเป็นส่วนประกอบไม่ใช่การปฏิเสธ
ที่นี่ x = ~ x ให้ผลลัพธ์ - (x + 1) เสมอ
x = ~ 2
- (2 + 1)
-3