ความแตกต่างระหว่าง>>>
และ>>
ตัวดำเนินการใน Java คืออะไร?
ความแตกต่างระหว่าง>>>
และ>>
ตัวดำเนินการใน Java คืออะไร?
คำตอบ:
>>
เลขคณิตเปลี่ยนไปทางขวา >>>
คือตรรกะที่ถูกต้อง
ในการเปลี่ยนแปลงทางคณิตศาสตร์บิตสัญญาณจะถูกขยายเพื่อรักษาความเซ็นของหมายเลข
ตัวอย่างเช่น: -2 แทนด้วย 8 บิตจะเป็น11111110
(เพราะบิตที่สำคัญที่สุดมีน้ำหนักเป็นลบ) เลื่อนไปทางขวาหนึ่งบิตโดยใช้การคำนวณทางคณิตศาสตร์จะให้คุณ11111111
หรือ -1 อย่างไรก็ตามการเลื่อนไปทางขวาแบบโลจิคัลไม่ได้สนใจว่าค่าอาจแสดงถึงหมายเลขที่ลงนามแล้ว มันย้ายทุกอย่างไปทางขวาและเติมจากซ้ายด้วย 0s การขยับของเรา -2 01111111
ขวาหนึ่งบิตโดยใช้ตรรกะกะจะให้
2^k
ฉันพบว่ามันแปลกที่นี่คือคำตอบของทุกคน สตริงของบิตไม่ใช่ตัวเลขและ>>
สามารถใช้ได้กับสตริงของบิตใด ๆ : มันจะทำสิ่งเดียวกันเสมอโดยไม่คำนึงถึงบทบาทที่สตริงของบิตกำลังเล่นอยู่และไม่ว่ามันจะมีแนวคิดของ 'สัญญาณ' หรือไม่ก็ตาม มันจะโอเคที่จะขยายคำตอบที่ดีของคุณแล้วด้วยการอภิปรายกรณีที่ตัวถูกดำเนินการของคุณจะไม่ถูกตีความว่าเป็นหมายเลขที่ลงนาม? การร้องเรียนของฉันสมเหตุสมผลหรือไม่
String
char[]
เขาไม่ได้พูดว่า a char
ไม่ใช่ตัวเลข; เขาแค่บอกว่ามันเป็นตัวเลขที่ไม่ได้ลงชื่อ ฉันคิดว่านั่นคือสิ่งที่เขาหายไป
>>>
ไม่มีการเปลี่ยนแปลง มันจะแทรก 0 >>
ลงนามและจะขยายบิตสัญญาณ
ผู้ประกอบการเปลี่ยนแปลงรวมถึงการเปลี่ยนแปลงทางด้านซ้าย
<<
ลงนามกะขวา>>
,>>>
และการเปลี่ยนแปลงทางด้านขวาได้รับการรับรองคุณค่าของ
n>>s
เป็นn
ขวาขยับs
ตำแหน่งบิตที่มีการลงชื่อเข้าใช้นามสกุลค่าของ
n>>>s
ถูกn
เลื่อนไปทางขวาs
ตำแหน่งบิตที่มีศูนย์ขยาย
System.out.println(Integer.toBinaryString(-1));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >> 16));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >>> 16));
// prints "1111111111111111"
เพื่อให้สิ่งต่าง ๆ ชัดเจนยิ่งขึ้นการเพิ่มคู่ที่เป็นบวก
System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"
เนื่องจากเป็นบวกทั้งกะที่ลงนามและไม่ได้ลงชื่อจะเพิ่ม 0 เหลือบิตมากที่สุด
1 >>> 32 == 1
พวกเขาเป็นทั้งกะขวา แต่>>>
เป็นunsigned
จากเอกสาร :
ตัวดำเนินการเลื่อนด้านขวาที่ไม่ได้ลงนาม ">>>" จะเลื่อนศูนย์เป็นตำแหน่งซ้ายสุดในขณะที่ตำแหน่งซ้ายสุดหลัง ">>" ขึ้นอยู่กับส่วนขยายของสัญญาณ
>>>
มันไม่ได้ลงชื่อ แต่ทำไม7>>32=7
? ฉันวิ่งห่วงที่ไม่เปลี่ยนแปลงหนึ่งในเวลาและเห็นว่าหลังจากที่มีการเปลี่ยนแปลงก็จะกลับมา32
7
วิธีเดียวที่สิ่งนี้ทำให้เข้าใจได้คือสำหรับแต่ละหมายเลขที่เลื่อนออกไปมันเข้าสู่ "วงนอก" หลังจาก32
เปลี่ยนไปมันก็กลับมาที่ตำแหน่งเดิม แต่ก็เห็นได้ชัดว่ายังไม่สมเหตุสมผล เกิดอะไรขึ้น?
for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));
) ถ้าคุณหมายถึงว่าทำไม>>32
ตัวเองกลับค่าเดิมที่เห็นนี้
ตรรกะการเลื่อนขวา ( v >>> n
) ส่งคืนค่าที่บิตในv
ถูกเลื่อนไปทางขวาโดยn
ตำแหน่งบิตและ 0 ถูกเลื่อนเข้ามาจากด้านซ้าย พิจารณาเปลี่ยนค่า 8 บิตเขียนในไบนารี:
01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000
ถ้าเราตีความบิตเป็นจำนวนเต็มไม่เป็นลบเชิงลบการเลื่อนขวาแบบลอจิคัลมีผลในการหารจำนวนด้วยกำลังที่สอดคล้องกันของ 2 อย่างไรก็ตามถ้าตัวเลขอยู่ในการแทนสองส่วนเติมเต็มการเลื่อนขวาเชิงตรรกะไม่ถูกต้องหารจำนวนลบ . ตัวอย่างเช่นการเลื่อนขวาที่สองด้านบนเลื่อน 128 ถึง 32 เมื่อบิตถูกตีความว่าเป็นตัวเลขที่ไม่ได้ลงนาม แต่มันจะเลื่อน -128 เป็น 32 เมื่อตามปกติใน Java บิตจะถูกตีความในส่วนเติมเต็มของสอง
ดังนั้นหากคุณขยับเพื่อหารด้วยกำลังสองคุณต้องการการคำนวณทางขวา ( v >> n
) มันส่งกลับค่าที่บิตในv
ได้ถูกเลื่อนไปทางขวาโดยn
ตำแหน่งบิตและสำเนาของบิตซ้ายสุดของ vจะถูกย้ายจากด้านซ้าย:
01111111 >> 2 = 00011111
10000000 >> 2 = 11100000
เมื่อบิตเป็นตัวเลขในการเป็นตัวแทนสองส่วนการเลื่อนขวาของเลขคณิตมีผลกระทบจากการหารด้วยกำลังสอง สิ่งนี้ใช้งานได้เพราะบิตทางซ้ายสุดคือบิตเครื่องหมาย การหารด้วยกำลังสองจะต้องรักษาเครื่องหมายเหมือนเดิม
>>>
จะใส่ 0 ในบิตซ้ายสุดเสมอในขณะที่>>
จะใส่ 1 หรือ 0 ขึ้นอยู่กับว่าสัญญาณของมันคืออะไร
อ่านเพิ่มเติมเกี่ยวกับผู้ประกอบการ Bitwise และ Bit Shift
>> Signed right shift
>>> Unsigned right shift
รูปแบบบิตถูกกำหนดโดยตัวถูกดำเนินการทางซ้ายและจำนวนตำแหน่งที่จะเลื่อนโดยตัวถูกดำเนินการทางขวา ตัวดำเนินการเลื่อนด้านขวาที่ไม่ได้ลงนาม>>>
จะเลื่อนศูนย์ให้อยู่ในตำแหน่งซ้ายสุด ,
ในขณะที่ตำแหน่งซ้ายสุดหลังจาก >>
ขึ้นอยู่กับส่วนขยายสัญญาณ
คำง่าย ๆ>>>
จะเลื่อนศูนย์ไปที่ตำแหน่งซ้ายสุดเสมอในขณะที่>>
การเลื่อนขึ้นอยู่กับเครื่องหมายของตัวเลขเช่น 1 สำหรับจำนวนลบและ 0 สำหรับจำนวนบวก
ตัวอย่างเช่นลองลบจำนวนบวก
int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));
System.out.println();
c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
เอาท์พุท:
11111111111111111111111111011001
11111111111111111111111101100100
111111111111111111111111011001
11111111111111111111111101100100
100110
10011000
100110
10011000
System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0'))
; Integer.MAX_VALUE : 01111111111111111111111111111111;
Integer.MIN_VALUE : 10000000000000000000000000000000;
-1 : 11111111111111111111111111111111;
0 : 00000000000000000000000000000000;
1 : 00000000000000000000000000000001
ตัวดำเนินการเลื่อนตรรกะด้านขวา ( >>> N
) เลื่อนบิตไปทางขวาตามตำแหน่ง N โดยละทิ้งเครื่องหมายบิตและเติมบิตที่เหลือมากที่สุด N ด้วย 0 ตัวอย่างเช่น:
-1 (in 32-bit): 11111111111111111111111111111111
หลังจากการ>>> 1
ดำเนินการกลายเป็น:
2147483647: 01111111111111111111111111111111
ตัวดำเนินการทางคณิตศาสตร์ shift shift ที่ถูกต้อง ( >> N
) ยังเลื่อนบิตไปทางขวาด้วยตำแหน่ง N แต่เก็บบิตสัญญาณไว้และวางบิต N ซ้ายสุดด้วย 1's ตัวอย่างเช่น:
-2 (in 32-bit): 11111111111111111111111111111110
หลังจากการ>> 1
ดำเนินการกลายเป็น:
-1: 11111111111111111111111111111111