ตัวดำเนินการเปลี่ยนบิตทำสิ่งที่ชื่อของพวกเขามีความหมาย พวกเขาเปลี่ยนบิต ต่อไปนี้เป็นคำแนะนำสั้น ๆ (หรือไม่สั้น) เกี่ยวกับตัวดำเนินการกะที่แตกต่างกัน
ผู้ประกอบการ
>>
เป็นตัวดำเนินการทางด้านขวาของเลขคณิต (หรือที่ลงชื่อ)
>>>
เป็นตัวดำเนินการ shift ที่เหมาะสม (หรือไม่ได้ลงชื่อ) ตรรกะ
<<
เป็นโอเปอเรเตอร์กะซ้ายและตอบสนองความต้องการของการเลื่อนทั้งแบบลอจิคัลและเลขคณิต
ทั้งหมดของผู้ประกอบการเหล่านี้สามารถนำไปใช้กับค่าจำนวนเต็ม ( int
, long
อาจจะเป็นshort
และbyte
หรือchar
) ในบางภาษาใช้ประกอบการเปลี่ยนไปใช้ประเภทข้อมูลใด ๆ ที่มีขนาดเล็กกว่าโดยอัตโนมัติปรับขนาดตัวถูกดำเนินการที่จะเป็นint
int
โปรดทราบว่า<<<
ไม่ใช่ตัวดำเนินการเนื่องจากจะซ้ำซ้อน
นอกจากนี้ทราบว่าC และ C ++ ไม่เห็นความแตกต่างระหว่างผู้ประกอบการเปลี่ยนแปลงทางด้านขวา พวกเขาให้บริการเฉพาะ>>
ผู้ประกอบการและพฤติกรรมการเปลี่ยนด้านขวาเป็นการใช้งานที่กำหนดไว้สำหรับประเภทที่ลงนาม คำตอบที่เหลือใช้ตัวดำเนินการ C # / Java
(ในการใช้งาน C และ C ++ ที่สำคัญทั้งหมดรวมถึง GCC และ Clang / LLVM >>
สำหรับประเภทที่ลงนามคือเลขคณิตรหัสบางอย่างถือว่านี่ แต่มันไม่ใช่สิ่งที่รับประกันมาตรฐาน แต่ก็ไม่ได้กำหนดแต่มาตรฐานนั้นต้องมีการนำไปใช้เพื่อกำหนด อีกวิธีหนึ่งอย่างไรก็ตามการเลื่อนซ้ายของตัวเลขที่มีเครื่องหมายลบนั้นเป็นพฤติกรรมที่ไม่ได้กำหนดไว้ (ล้นจำนวนเต็มที่ลงนามแล้ว) ดังนั้นหากคุณไม่จำเป็นต้องใช้การเลื่อนขวาแบบเลขคณิตคุณควรทำการเปลี่ยนบิตด้วยประเภทที่ไม่ได้ลงนาม)
เลื่อนไปทางซ้าย (<<)
จำนวนเต็มถูกเก็บไว้ในหน่วยความจำเป็นชุดของบิต ตัวอย่างเช่นหมายเลข 6 ที่จัดเก็บเป็น 32 บิตint
จะเป็น:
00000000 00000000 00000000 00000110
การเลื่อนรูปแบบบิตนี้ไปทางซ้ายหนึ่งตำแหน่ง ( 6 << 1
) จะส่งผลให้หมายเลข 12:
00000000 00000000 00000000 00001100
อย่างที่คุณเห็นตัวเลขได้เลื่อนไปทางซ้ายหนึ่งตำแหน่งและตัวเลขสุดท้ายทางด้านขวาเต็มไปด้วยศูนย์ นอกจากนี้คุณยังอาจจะทราบว่าการขยับซ้ายจะเทียบเท่ากับการคูณโดยอำนาจของ 2 ดังนั้น6 << 1
จะเทียบเท่ากับ6 * 2
และเทียบเท่ากับ6 << 3
6 * 8
คอมไพเลอร์การปรับให้เหมาะสมที่ดีจะแทนที่การคูณด้วยการเลื่อนเมื่อทำได้
การขยับแบบไม่เป็นวงกลม
โปรดทราบว่าสิ่งเหล่านี้ไม่ใช่การเปลี่ยนแปลงแบบวงกลม เลื่อนค่านี้ไปทางซ้ายทีละตำแหน่ง ( 3,758,096,384 << 1
):
11100000 00000000 00000000 00000000
ผลลัพธ์ใน 3,221,225,472:
11000000 00000000 00000000 00000000
ตัวเลขที่ได้รับการเลื่อน "ปิดท้าย" จะหายไป มันไม่ได้พันรอบ
ลอจิกกะขวา (>>>)
การเลื่อนขวาแบบลอจิคัลคือการสนทนาไปทางซ้าย แทนที่จะขยับบิตไปทางซ้ายพวกเขาก็เลื่อนไปทางขวา ตัวอย่างเช่นการขยับหมายเลข 12:
00000000 00000000 00000000 00001100
ไปทางขวาโดยตำแหน่งหนึ่ง ( 12 >>> 1
) จะได้รับ 6 ดั้งเดิมคืนของเรา:
00000000 00000000 00000000 00000110
ดังนั้นเราจะเห็นว่าการขยับไปทางขวาเทียบเท่ากับการหารด้วยพลังของ 2
บิตที่หายไปจะหายไป
อย่างไรก็ตามกะไม่สามารถเรียกคืนบิต "ที่หายไป" ได้ ตัวอย่างเช่นถ้าเราเปลี่ยนรูปแบบนี้:
00111000 00000000 00000000 00000110
ทางซ้าย 4 ตำแหน่ง ( 939,524,102 << 4
) เราได้รับ 2,147,483,744:
10000000 00000000 00000000 01100000
แล้วขยับกลับ ( (939,524,102 << 4) >>> 4
) เราจะได้ 134,217,734:
00001000 00000000 00000000 00000110
เราไม่สามารถคืนค่าเดิมของเราได้เมื่อเราทำบิตหาย
การเลื่อนขวาของเลขคณิต (>>)
การเลื่อนขวาของเลขคณิตนั้นเหมือนกับการเลื่อนขวาแบบลอจิคัลยกเว้นการเว้นระยะห่างจากศูนย์มันจะมีบิตที่สำคัญที่สุด นี่เป็นเพราะบิตที่สำคัญที่สุดคือบิตเครื่องหมายหรือบิตที่แยกความแตกต่างระหว่างจำนวนบวกและลบ ด้วยการเติมด้วยบิตที่สำคัญที่สุดการเลื่อนขวาของเลขคณิตจะเป็นการรักษาเครื่องหมาย
ตัวอย่างเช่นหากเราตีความรูปแบบบิตนี้เป็นจำนวนลบ:
10000000 00000000 00000000 01100000
เรามีหมายเลข -2,147,483,552 การเลื่อนสิ่งนี้ไปทางขวา 4 ตำแหน่งพร้อมการเปลี่ยนแปลงทางคณิตศาสตร์ (-2,147,483,552 >> 4) จะทำให้เรา:
11111000 00000000 00000000 00000110
หรือหมายเลข -134,217,722
ดังนั้นเราจะเห็นว่าเราได้รักษาเครื่องหมายของตัวเลขติดลบของเราไว้โดยใช้การเลื่อนขวาแบบเลขคณิตแทนการเลื่อนขวาแบบตรรกะ และอีกครั้งเราจะเห็นว่าเรากำลังทำการหารด้วยอำนาจของ 2