1. เลื่อนไปทางซ้ายตามบิต
Java ยังมีตัวดำเนินการเลื่อนระดับบิต 3 ตัว : หากคุณต้องการจริงๆ คุณสามารถเลื่อนบิตทั้งหมดของตัวเลขหลายๆ ตำแหน่งไปทางซ้ายหรือขวาได้
หากต้องการเลื่อนบิตของตัวเลขไปทางซ้าย คุณต้องใช้ตัวดำเนินการเลื่อนไปทางซ้ายในระดับบิต นี่คือวิธีการเขียน:
a << b
a
ตัวเลขที่บิตเลื่อนไปทางซ้ายคือจำนวนใด และ b
เป็นตัวเลขที่ระบุจำนวนครั้งที่ต้องเลื่อนบิตของตัวเลขa
ไปทางซ้าย ระหว่างการดำเนินการนี้ บิตลำดับต่ำที่เพิ่มทางด้านขวาจะเป็นศูนย์
ตัวอย่าง:
ตัวอย่าง | ผลลัพธ์ |
---|---|
|
|
|
|
|
|
|
|
การเลื่อนหนึ่งหลักไปทางซ้ายมีผลเหมือนกับการคูณจำนวนด้วย 2
ต้องการคูณจำนวนด้วย 16 หรือไม่? 16 เท่ากับ 2 4 คุณจึงเลื่อนตัวเลข 4 หลักไปทางซ้าย
2. เลื่อนบิตไปทางขวา
บิตสามารถเลื่อนไปทางขวาได้เช่นกัน ในการดำเนินการนี้ ให้ใช้ตัวดำเนินการเลื่อนขวาระดับบิต นี่คือวิธีการเขียน:
a >> b
a
จำนวนที่บิตถูกเลื่อนอยู่ที่ไหน และ b
จำนวนครั้งที่จะเลื่อนบิตของตัวเลขa
ไปทางขวา
ตัวอย่าง:
ตัวอย่าง | ผลลัพธ์ |
---|---|
|
|
|
|
|
|
|
|
การเลื่อนตัวเลขไปทางขวาหนึ่งหลักมีผลเหมือนกับการหารตัวเลขด้วย 2
ระหว่างการดำเนินการนี้ บิตลำดับสูงที่เพิ่มทางด้านซ้ายจะเป็นศูนย์แต่ไม่เสมอไป !
บิตซ้ายสุดของตัวเลขที่มีเครื่องหมายเรียกว่าบิตเครื่องหมายถ้าตัวเลขเป็นบวก มันคือ0
; แต่ถ้าตัวเลขเป็นลบ บิตนี้1
คือ
เมื่อเลื่อนบิตของตัวเลขไปทางขวา ค่าของบิตเครื่องหมายจะเปลี่ยนไปตามปกติด้วย และเครื่องหมายของตัวเลขจะหายไป ดังนั้น สำหรับจำนวนลบ (โดยที่บิตซ้ายสุดคือ1
) บิตนี้จะได้รับการดูแลเป็นพิเศษ เมื่อเลื่อนบิตของตัวเลขไปทางขวา a 0
จะถูกเพิ่มทางซ้ายหากบิตซ้ายสุดคือ0
และ1
เพิ่ม a ทางซ้ายหากบิตซ้ายสุด1
คือ
แต่ในตัวอย่างข้างต้น ดูเหมือนจะไม่เป็นผลลัพธ์ ทำไม เนื่องจากจำนวนเต็มตัวอักษรคือint
s และ จริง ๆ แล้วหมายถึง นั่นคือบิตซ้ายสุดเป็นศูนย์0b11111111
0b00000000000000000000000011111111
โปรแกรมเมอร์หลายคนรู้สึกผิดหวังกับพฤติกรรมการเลื่อนไปทางขวานี้ และต้องการให้ตัวเลขเป็นเลขศูนย์เสมอ ดังนั้น Java จึงเพิ่ม ตัว ดำเนินการ shift ขวา อีกตัว
นี่คือวิธีการเขียน:
a >>> b
a
จำนวนที่บิตถูกเลื่อนอยู่ที่ไหน และ b
จำนวนครั้งที่จะเลื่อนบิตของตัวเลขa
ไปทางขวา a
ตัวดำเนินการนี้จะต่อท้ายเลข ศูนย์ทางด้านซ้ายเสมอ โดยไม่คำนึงถึงค่าเดิมของบิตเครื่องหมายของตัวเลข
3. การทำงานกับแฟล็ก
โปรแกรมเมอร์สร้างสาขาการศึกษาใหม่เกือบทั้งหมดบนพื้นฐานของการดำเนินการระดับบิตและกะ: การทำงานกับแฟล็ก
เมื่อคอมพิวเตอร์มีหน่วยความจำน้อยมาก การยัดข้อมูลจำนวนมากให้เป็นตัวเลขเดียวจึงเป็นที่นิยมอย่างมาก ตัวเลขถือเป็นอาร์เรย์ของบิต โดย int คือ 32 บิต และ long คือ 64 บิต
คุณสามารถเขียนข้อมูลจำนวนมากในตัวเลขดังกล่าว โดยเฉพาะอย่างยิ่งถ้าคุณต้องการเก็บค่า ตรรกะ ( true
หรือ ) false
หนึ่งเดียวlong
เปรียบเสมือนboolean
อาร์เรย์ที่ประกอบด้วย 64 องค์ประกอบ บิตเหล่านี้เรียกว่าแฟล็กและถูกจัดการโดยใช้การดำเนินการต่อไปนี้:
-
ตั้งธง(ทำให้บิตเฉพาะเท่ากับ
1
) -
ตั้งค่าสถานะใหม่(ทำให้บิตเฉพาะเท่ากับ
0
) -
ตรวจสอบธง(ตรวจสอบค่าของบิตเฉพาะ)
และนี่คือวิธีการดำเนินการกับตัวดำเนินการระดับบิต
การตั้งธง
ในการตั้งค่าบิตเฉพาะเป็น1
คุณจะต้องดำเนินการตามบิต OR ระหว่างจำนวนบิตที่คุณต้องการตั้งค่ากับตัวเลขที่สร้างขึ้นเป็นพิเศษ โดยที่บิตนั้น1
คือ
ตัวอย่างเช่น สมมติว่าคุณมีตัวเลข0b00001010
และคุณต้องตั้งค่าบิตที่ 5 1
เป็น ในกรณีนี้ คุณต้อง:
0b00001010 | 0b00010000 = 0b00011010
หากบิตที่ 5 ถูกตั้งค่าเป็นหนึ่งแล้ว ก็จะไม่มีอะไรเปลี่ยนแปลง
โดยทั่วไป การดำเนินการตั้งค่าสถานะสามารถเขียนได้ดังนี้
a | (1 << b)
หมายเลขa
ที่จะตั้งค่าบิตเป็น1
. และb
เป็นตำแหน่งของบิตที่จะกำหนด การใช้ตัวดำเนินการกะซ้ายนั้นสะดวกมากที่นี่ เนื่องจากคุณสามารถบอกได้ทันทีว่าเรากำลังทำงานกับบิตใด
การรีเซ็ตค่าสถานะ
หากต้องการรีเซ็ตบิตใดบิตหนึ่ง (เช่น ตั้งค่าเป็น0
) โดยไม่รบกวนบิตอื่น คุณต้องดำเนินการ&
ระหว่างหมายเลขของบิตที่คุณต้องการรีเซ็ต (เช่น ตั้งค่าเป็น0
) กับตัวเลขที่สร้างขึ้นเป็นพิเศษ โดยที่บิตทั้งหมดมีค่าเท่ากัน1
ยกเว้น สำหรับบิตที่คุณต้องการรีเซ็ต
ตัวอย่างเช่น สมมติว่าคุณมีตัวเลข0b00001010
และคุณต้องตั้งค่าบิตที่ 4 0
เป็น ในกรณีนี้ คุณต้อง:
0b00001010 & 0b11110111 = 0b00000010
หากบิตที่ 4 ถูกตั้งค่าเป็นศูนย์แล้ว ก็จะไม่มีอะไรเปลี่ยนแปลง
โดยทั่วไป การดำเนินการรีเซ็ตแฟล็กสามารถเขียนได้ดังนี้
a & ~(1 << b)
หมายเลขa
ที่จะรีเซ็ตบิตเป็น0
. และb
เป็นตำแหน่งของบิตที่จะล้าง
ในการรับตัวเลขที่บิตทั้งหมดอยู่1
ยกเว้นบิตที่เราต้องการให้เป็นศูนย์ ก่อนอื่นเราจะเลื่อน ตำแหน่ง b ไปทางซ้าย 1 ตำแหน่ง จากนั้นใช้NOT
ตัวดำเนินการระดับบิตเพื่อสลับผลลัพธ์
กำลังตรวจสอบธง
นอกเหนือจากการตั้งค่าหรือรีเซ็ตแฟล็กเฉพาะแล้ว บางครั้งคุณเพียงแค่ต้องตรวจสอบว่ามีการตั้งค่าแฟล็กหรือไม่ เช่น บิตหนึ่งเท่ากับหรือ1
ไม่ &
นี่ค่อนข้างง่าย ที่จะทำด้วยบิต
ตัวอย่างเช่น สมมติว่าคุณต้องการตรวจสอบว่าบิตที่ 4 ถูกตั้งค่า1
เป็นตัวเลขหรือ0b00001010
ไม่ จากนั้นคุณต้องทำสิ่งนี้:
if ( (0b00001010 & 0b00001000) == 0b00001000 )
โดยทั่วไป การดำเนินการตรวจสอบแฟล็กสามารถเขียนได้ดังนี้
(a & (1 << b)) == (1 << b)
a
หมายเลขที่มีการตรวจสอบบิตอยู่ที่ไหน และb
เป็นตำแหน่งของบิตที่จะตรวจสอบ
4. การเข้ารหัส
XOR
โปรแกรมเมอร์มักใช้การดำเนินการระดับบิต เพื่อการเข้ารหัสอย่างง่าย โดยทั่วไปแล้ว การเข้ารหัสดังกล่าวจะมีลักษณะดังนี้:
result = number ^ password;
number
ข้อมูลที่เราต้องการเข้ารหัสอยู่ที่ไหนpassword
เป็นหมายเลขพิเศษที่ใช้เป็น "รหัสผ่าน" สำหรับข้อมูล และresult
เป็นหมายเลขที่เข้ารหัส
number == (number ^ password) ^ password;
สิ่งสำคัญที่นี่คือเมื่อXOR
ใส่โอเปอเรเตอร์กับตัวเลขสองครั้ง มันจะสร้างตัวเลขเดิมโดยไม่คำนึงถึง "รหัสผ่าน"
ในการกู้คืนnumber
จากencrypted result
คุณเพียงแค่ต้องดำเนินการอีกครั้ง:
original number = result ^ password;
ตัวอย่าง:
class Solution
{
public static int[] encrypt(int[] data, int password)
{
int[] result = new int[data.length];
for (int i = 0; i < data.length; i++)
result[i] = data[i] ^ password;
return result;
}
public static void main(String[] args)
{
int[] data = {1, 3, 5, 7, 9, 11};
int password = 199;
// Encrypt the array of data
int[] encrypted = encrypt(data, password);
System.out.println(Arrays.toString(encrypted));
// Decrypt the array of data
int[] decrypted = encrypt(encrypted, password);
System.out.println(Arrays.toString(decrypted));
}
}
GO TO FULL VERSION