[Python] 通過各種實例深入理解位元運算符

電腦採用由0和1組成的二進制來儲存和處理資訊。這些0和1被稱為「位元(bit)」。位元運算子即基於這些位元來進行運算。以下,我們將詳細介紹各個運算子。

&(位元AND運算子)

AND運算子對於兩個數字的二進制表示中,只有當相同位置的位元都是1時,結果才會是1;否則結果是0。

舉例說明,用數字13和10:

  • 13在二進制中表示為1101
  • 10在二進制中表示為1010

根據與運算比對每一位置的位元:

  • 最右邊(個位): 1與0比對結果為0(兩者皆非1則為0)。
  • 接下來(二位): 0與1比對結果為0。
  • 接下來(四位): 1與0比對結果為0。
  • 最左邊(八位): 1與1比對結果為1。

因此,11011010的結果是1000。十進制表示為8。

python
a = 13
b = 10
result = a & b
print(result)  # 8

此程式碼輸出13與10的與運算結果。輸出值為8。


|(位元OR運算子)

OR運算子對於兩數字的二進制表示,只要同位置的其中一位是1,結果就是1;只有當兩者都是0時,結果才是0。

以數字6和9為例說明:

  • 6在二進制中表示為110
  • 9在二進制中表示為1001

根據或運算比對每一位置的位元:

  • 最右邊(個位): 0與1比對結果為1。
  • 接下來(二位): 1與0比對結果為1。
  • 接下來(四位): 1與0比對結果為1。
  • 最左邊(八位): 0與1比對結果為1。

因此,1101001的結果是1101。十進制表示為13。

python
a = 6
b = 9
result = a | b
print(result)  # 13

此程式碼輸出6與9的或運算結果。輸出值為13。


^(位元XOR運算子)

XOR運算子在兩數字的二進制表示中,同位置的位元如果不同則結果為1,相同則為0。

以數字10和12為例:

  • 10在二進制中表示為1010
  • 12在二進制中表示為1100

根據互斥或運算比對每一位置的位元:

  • 最右邊(個位): 0與0比對結果為0。
  • 接下來(二位): 1與0比對結果為1。
  • 接下來(四位): 0與1比對結果為1。
  • 最左邊(八位): 1與1比對結果為0。

因此,1010 互斥或 1100的結果是0110。十進制表示為6。

python
a = 10
b = 12
result = a ^ b
print(result)  # 6

此程式碼輸出10與12的互斥或運算結果。輸出值為6。


~(位元NOT運算子)

NOT運算符會將指定數字的二進位表示中的所有位元反轉。也就是說,1會變成0,0會變成1。

以數字7為例:

  • 7的二進制表示為111

依據NOT運算對每位進行反轉:

  • 最右側(個位):1反轉為0。
  • 次右側(十位):1反轉為0。
  • 最左側(百位):1反轉為0。

因此,111的NOT運算結果是000。但NOT運算的特性是,正整數將變為負整數,負整數將變為正整數,實際上其值是-8

python
a = 7
result = ~a
print(result)  # -8

上述代碼顯示了7的NOT運算結果。輸出值是-8。

註: 對於NOT運算符,需要更深入了解二的補數表示。這裡簡單描述,但事實上,計算機將負數存儲為二的補數形式,並通過此執行減法運算。這就是為什麼NOT運算結果如此的原因。


<<(左位移運算子)

左移運算符將數字的位元向左移指定的位數。當位元從左側移出時,它會被丟棄,右側則填充0。

例如,將數字5左移2位:

  • 5的二進制表示為101

5左移2位後為:

  • 101 -> 10100

因此,101 << 2的結果是10100。在十進制中,其值為20。

python
a = 5
result = a << 2
print(result)  # 20

上述代碼顯示了將5左移2位的結果。輸出值是20。

>>(右位移運算子)

右移運算符將數字的位元向右移指定的位數。當位元從右側移出時,它會被丟棄,左側則填充原數字的最高位(符號位)。

例如,將數字18右移2位:

  • 18的二進制表示為10010

18右移2位後為:

  • 10010 -> 00100

因此,10010 >> 2的結果是00100。在十進制中,其值為4。

python
a = 18
result = a >> 2
print(result)  # 4

上述代碼顯示了將18右移2位的結果。輸出值是4。

註: 左移和右移運算符都是用於移動給定數字的位元。它們主要用於加快乘法和除法運算,這些運算在硬體級別上非常快速地執行。


位元運算子之應用

位元運算子不僅限於簡單的數值計算,它在多個領域都有其出色的運用。特別是在低階程式設計中,這種運用方式更為普遍。以下是位元運算子主要的應用方式及說明。

1. 記憶體節省

位元運算子能有效地存儲多個標記(flag)。因為每一個標記可以被表示為一個位元,所以一個32位元的整數變數就可以存儲32種不同的狀態或選項。這比使用多個布林變數更能節省記憶體空間。

python
OPTION_A = 0b00000001  # 1
OPTION_B = 0b00000010  # 2
OPTION_C = 0b00000100  # 4

options = OPTION_A | OPTION_C  # 啟用OPTION_A及OPTION_C

2. 快速運算

由於位元運算相對於數學運算來說速度較快,因此在性能要求高的場景下,使用位元運算可以提升計算速度。例如,使用位移運算代替乘法和除法可以更快地得到結果。

python
number = 5
double_number = number << 1  # 5 * 2 = 10
half_number = number >> 1    # 5 / 2 = 2

3. 資料壓縮與加密

位元運算子在資料壓縮和加密中扮演了關鍵角色。

XOR運算子在兩位元相同時回傳0,不同時回傳1。利用這個特性,可以實現簡單的加密和解密方法。例如,將某數據和密鑰進行XOR運算,可以將原始數據加密。再次使用同一密鑰對加密數據進行XOR運算,則可以還原原始數據。

python
data = 0b10101010
key = 0b11110000

# 加密
encrypted = data ^ key  # 結果: 0b01011010

# 解密
decrypted = encrypted ^ key  # 還原為原始的data值 0b10101010

4. 硬體控制

位元運算子在硬體控制,尤其是嵌入式系統中非常重要。

位元設定與清除 在需要啟用或禁用硬體特定功能的暫存器中,通常使用位元運算子來設定或清除特定的位元。

python
# 位元設定 (使用OR運算)
register = 0b00000000
BIT3 = 0b00001000

register |= BIT3  # 設定第三位元

# 位元清除 (使用AND及NOT運算)
register &= ~BIT3  # 清除第三位元

位元切換 要切換特定位元的狀態,可以使用XOR運算。

python
BIT2 = 0b00000100
register ^= BIT2  # 切換第二位元

5. 遮罩與過濾

位元遮罩用於選擇或更改數據的特定位元。

例如,要從24位元的RGB顏色中分離紅色、綠色和藍色組件,可以使用以下遮罩。

python
color = 0x66CCFF  # 隨意色彩值

RED_MASK = 0xFF0000
GREEN_MASK = 0x00FF00
BLUE_MASK = 0x0000FF

red_component = (color & RED_MASK) >> 16
green_component = (color & GREEN_MASK) >> 8
blue_component = color & BLUE_MASK

通過位元運算子進行遮罩非常高效,且在多種領域中都有其廣泛的應用。這些技術在資料處理、圖形、通信等領域都有其優越性能。


位元運算子在包括Python在內的許多程式語言中,都是一個強大的工具。對於初學者,起初可能會覺得這些概念有些複雜,但希望透過這些簡明的示例和說明,能幫助你掌握基礎知識。

位元運算子能在多種情境中發揮其效能,尤其在需要優化和效率的情境下。雖然在初學時可能會覺得有些難以理解和應用,但隨著程式設計經驗的累積,你將能更深入地理解位元運算子的重要性和應用範疇。希望你能持續學習和實踐,將你的基本功鍛煉得更為堅固。


© Copyright 2023 CLONE CODING