1. เลื่อนไปทางซ้ายตามบิต

Java ยังมีตัวดำเนินการเลื่อนระดับบิต 3 ตัว : หากคุณต้องการจริงๆ คุณสามารถเลื่อนบิตทั้งหมดของตัวเลขหลายๆ ตำแหน่งไปทางซ้ายหรือขวาได้

หากต้องการเลื่อนบิตของตัวเลขไปทางซ้าย คุณต้องใช้ตัวดำเนินการเลื่อนไปทางซ้ายในระดับบิต นี่คือวิธีการเขียน:

a << b

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

ตัวอย่าง:

ตัวอย่าง ผลลัพธ์
0b00000011 << 1
0b00000110
0b00000011 << 2
0b00001100
0b00000011 << 5
0b01100000
0b00000011 << 20
0b001100000000000000000000

การเลื่อนหนึ่งหลักไปทางซ้ายมีผลเหมือนกับการคูณจำนวนด้วย 2

ต้องการคูณจำนวนด้วย 16 หรือไม่? 16 เท่ากับ 2 4 คุณจึงเลื่อนตัวเลข 4 หลักไปทางซ้าย


2. เลื่อนบิตไปทางขวา

บิตสามารถเลื่อนไปทางขวาได้เช่นกัน ในการดำเนินการนี้ ให้ใช้ตัวดำเนินการเลื่อนขวาระดับบิต นี่คือวิธีการเขียน:

a >> b

aจำนวนที่บิตถูกเลื่อนอยู่ที่ไหน และ bจำนวนครั้งที่จะเลื่อนบิตของตัวเลขaไปทางขวา

ตัวอย่าง:

ตัวอย่าง ผลลัพธ์
0b11000011 >> 1
0b01100001
0b11000011 >> 2
0b00110000
0b11000011 >> 5
0b00000110
0b11000011 >> 20
0b00000000

การเลื่อนตัวเลขไปทางขวาหนึ่งหลักมีผลเหมือนกับการหารตัวเลขด้วย 2

ระหว่างการดำเนินการนี้ บิตลำดับสูงที่เพิ่มทางด้านซ้ายจะเป็นศูนย์แต่ไม่เสมอไป !

สำคัญ!

บิตซ้ายสุดของตัวเลขที่มีเครื่องหมายเรียกว่าบิตเครื่องหมายถ้าตัวเลขเป็นบวก มันคือ0; แต่ถ้าตัวเลขเป็นลบ บิตนี้1คือ

เมื่อเลื่อนบิตของตัวเลขไปทางขวา ค่าของบิตเครื่องหมายจะเปลี่ยนไปตามปกติด้วย และเครื่องหมายของตัวเลขจะหายไป ดังนั้น สำหรับจำนวนลบ (โดยที่บิตซ้ายสุดคือ1) บิตนี้จะได้รับการดูแลเป็นพิเศษ เมื่อเลื่อนบิตของตัวเลขไปทางขวา a 0จะถูกเพิ่มทางซ้ายหากบิตซ้ายสุดคือ0และ1เพิ่ม a ทางซ้ายหากบิตซ้ายสุด1คือ

แต่ในตัวอย่างข้างต้น ดูเหมือนจะไม่เป็นผลลัพธ์ ทำไม เนื่องจากจำนวนเต็มตัวอักษรคือints และ จริง ๆ แล้วหมายถึง นั่นคือบิตซ้ายสุดเป็นศูนย์0b111111110b00000000000000000000000011111111

โปรแกรมเมอร์หลายคนรู้สึกผิดหวังกับพฤติกรรมการเลื่อนไปทางขวานี้ และต้องการให้ตัวเลขเป็นเลขศูนย์เสมอ ดังนั้น 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));
   }
}