1. Dịch chuyển trái theo chiều bit
Java cũng có 3 toán tử dịch chuyển bit : Nếu thực sự cần, bạn có thể rất đơn giản dịch chuyển tất cả các bit của một số sang trái hoặc sang phải một số vị trí.
Để dịch chuyển các bit của một số sang trái, bạn cần toán tử dịch chuyển trái theo từng bit . Đây là cách nó được viết:
a << b
Đâu a
là số có các bit đang được dịch chuyển và b
là một số cho biết số lần dịch chuyển các bit của số đó a
sang trái. Trong quá trình hoạt động này, các bit thứ tự thấp được thêm vào bên phải là số không.
Ví dụ:
Ví dụ | Kết quả |
---|---|
|
|
|
|
|
|
|
|
Dịch chuyển một chữ số sang trái có tác dụng tương tự như nhân một số với 2.
Muốn nhân một số với 16? 16 cũng giống như 2 4 . Vì vậy, bạn di chuyển 4 chữ số sang trái
2. Dịch chuyển bit sang phải
Các bit cũng có thể được chuyển sang bên phải. Để thực hiện việc này, hãy sử dụng toán tử dịch chuyển phải theo bit . Đây là cách nó được viết:
a >> b
Đâu a
là số có các bit đang được dịch chuyển và b
là số lần dịch chuyển các bit của số đó a
sang phải.
Ví dụ:
Ví dụ | Kết quả |
---|---|
|
|
|
|
|
|
|
|
Dịch chuyển một chữ số sang phải có tác dụng tương tự như chia một số cho 2.
Trong quá trình hoạt động này, các bit bậc cao được thêm vào bên trái là số không, nhưng không phải lúc nào cũng vậy !
Bit ngoài cùng bên trái của một số có dấu được gọi là bit dấu : nếu số đó là số dương thì nó là 0
; nhưng nếu số âm, bit này là 1
.
Khi dịch chuyển các bit của một số sang phải, giá trị của bit dấu thường cũng sẽ dịch chuyển và dấu của số đó sẽ bị mất. Theo đó, đối với các số âm (trong đó bit ngoài cùng bên trái là 1
), bit này được xử lý đặc biệt. Khi dịch chuyển các bit của một số sang bên phải, a 0
được thêm vào bên trái nếu bit ngoài cùng bên trái là 0
, và a 1
được thêm vào bên trái nếu bit ngoài cùng bên trái là 1
.
Nhưng trong ví dụ trên, đó dường như không phải là kết quả. Tại sao? Bởi vì số nguyên bằng chữ là int
s, và thực sự có nghĩa là . Nghĩa là, bit ngoài cùng bên trái bằng không.0b11111111
0b00000000000000000000000011111111
Nhiều lập trình viên thất vọng với hành vi dịch chuyển phải này và muốn số luôn được đệm bằng số không. Vì vậy, Java đã thêm một toán tử dịch chuyển phải khác .
Đây là cách nó được viết:
a >>> b
Đâu a
là số có các bit đang được dịch chuyển và b
là số lần dịch chuyển các bit của số đó a
sang phải. Toán tử này luôn nối các số 0 ở bên trái, bất kể giá trị ban đầu của bit dấu của số đó a
.
3. Làm việc với cờ
Các lập trình viên đã tạo ra một lĩnh vực nghiên cứu gần như hoàn toàn mới trên cơ sở hoạt động theo bit và dịch chuyển: làm việc với các cờ.
Khi máy tính có rất ít bộ nhớ, việc nhồi nhét nhiều thông tin vào một con số rất phổ biến. Một số được coi là một mảng bit: int là 32 bit và long là 64 bit.
Bạn có thể viết nhiều thông tin trong một số như vậy, đặc biệt nếu bạn cần lưu trữ các giá trị logic ( true
hoặc false
). Một đĩa đơn long
giống như một boolean
mảng bao gồm 64 phần tử. Các bit này được gọi là cờ và được thao tác bằng các thao tác sau:
-
bộ cờ(tạo một bit cụ thể bằng
1
) -
đặt lại cờ(tạo một bit cụ thể bằng
0
) -
kiểm tra cờ(kiểm tra giá trị của một bit cụ thể)
Và đây là cách nó được thực hiện với toán tử bitwise.
Đặt cờ
Để đặt một bit cụ thể thành 1
, bạn cần thực hiện thao tác OR theo bit giữa số có bit mà bạn muốn đặt và một số được tạo đặc biệt, trong đó chỉ có bit đó là 1
.
Ví dụ: giả sử bạn có số 0b00001010
và bạn cần đặt bit thứ 5 thành 1
. Trong trường hợp đó, bạn cần phải:
0b00001010 | 0b00010000 = 0b00011010
Nếu bit thứ 5 đã được đặt thành một, thì sẽ không có gì thay đổi.
Nói chung, thao tác đặt cờ có thể được viết như sau
a | (1 << b)
Đâu a
là số có bit sẽ được đặt thành 1
. Và b
là vị trí của bit được thiết lập. Sử dụng toán tử dịch trái ở đây cực kỳ tiện lợi, vì bạn có thể biết ngay chúng ta đang làm việc với bit nào.
Đặt lại cờ
Để đặt lại một bit cụ thể (nghĩa là đặt thành 0
) mà không làm phiền các bit khác, bạn cần thực hiện thao &
tác giữa số có bit mà bạn muốn đặt lại (tức là đặt thành 0
) và một số được tạo đặc biệt, trong đó tất cả các bit đều bằng 1
ngoại trừ cho bit bạn muốn thiết lập lại.
Ví dụ: giả sử bạn có số 0b00001010
và bạn cần đặt bit thứ 4 thành 0
. Trong trường hợp đó, bạn cần phải:
0b00001010 & 0b11110111 = 0b00000010
Nếu bit thứ 4 đã được đặt thành 0, thì sẽ không có gì thay đổi.
Nói chung, hoạt động đặt lại cờ có thể được viết như sau
a & ~(1 << b)
Đâu a
là số có bit sẽ được đặt lại thành 0
. Và b
là vị trí của bit được xóa.
Để có được một số mà tất cả các bit đều 1
ngoại trừ số mà chúng ta muốn bằng 0, trước tiên chúng ta dịch chuyển 1 vị trí b sang trái, sau đó sử dụng NOT
toán tử theo chiều bit để đảo ngược kết quả.
Kiểm tra cờ
Ngoài việc đặt hoặc đặt lại một cờ cụ thể, đôi khi bạn chỉ cần kiểm tra xem một cờ đã cho có được đặt hay không, tức là liệu một bit nhất định có bằng 1
. Điều này khá dễ thực hiện với bitwise &
.
Ví dụ: giả sử bạn cần kiểm tra xem bit thứ 4 có được đặt thành 1
số hay không 0b00001010
. Sau đó, bạn cần phải làm điều này:
if ( (0b00001010 & 0b00001000) == 0b00001000 )
Nói chung, thao tác kiểm tra cờ có thể được viết như sau
(a & (1 << b)) == (1 << b)
Đâu a
là số có bit đang được kiểm tra. Và b
là vị trí của bit được kiểm tra.
4. Mã hóa
Hoạt động bitwise XOR
thường được các lập trình viên sử dụng để mã hóa đơn giản. Nói chung, mã hóa như vậy trông như thế này:
result = number ^ password;
number
Dữ liệu chúng tôi muốn mã hóa ở đâu , password
là một số đặc biệt được sử dụng làm "mật khẩu" cho dữ liệu và result
là số được mã hóa.
number == (number ^ password) ^ password;
Điều quan trọng ở đây là khi XOR
toán tử được áp dụng cho một số hai lần, nó sẽ tạo ra số ban đầu, bất kể "mật khẩu" là gì.
Để khôi phục number
từ encrypted result
, bạn chỉ cần thực hiện lại thao tác:
original number = result ^ password;
Ví dụ:
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