位運算符通常在圖形、圖像處理和創建設備驅動等底層開發中使用。使用位運算符可以直接操作數值的原始 bit 位,尤其是在使用自定義的協議進行通信時,使用位運算符對原始數據進行編碼和解碼也非常有效。
位運算符對於初學者來說有些難度,因此初學者可先跳過本節內容。
位運算符的操作對象是整數類型,它會把數字看做對應的二進制數來進行計算。Python 支持的位運算符如表 1 所示。
| 位運算符 | 說 明 | 使用形式 | 舉 例 |
|---|---|---|---|
| & | 按位與 | a & b | 4 & 5 |
| | | 按位或 | a | b | 4 | 5 |
| ^ | 按位異或 | a ^ b | 4 ^ 5 |
| ~ | 按位取反 | ~a | ~4 |
| << | 按位左移 | a << b | 4 << 2,表示數字 4 按位左移 2 位 |
| >> | 按位右移 | a >> b | 4 >> 2,表示數字 4 按位右移 2 位 |
& 按位與運算符
按位與運算的運算符是 &,它有 2 個操作數,其運算法則是,按位將 2 個操作數對應的二進制數一一對應,只有對應數位都是 1 時,此為對應的結果位才是 1;反之,就是 0。
按位與運算的運算法則如表 2 所示。
| 第一個操作數 | 第二個操作數 | 結果位的值 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
例如,在 Python 交互式解釋器中,計算 12 & 8 的值,執行過程如下:
>>> 12 & 8
8
計算過程如圖 3 所示。
圖 3 12 & 8 的計算過程
| 按位或運算符
按位或運算的運算符是 |,它有 2 個操作數,運算法則是,按位將 2 個操作數對應的二進制數一一對應,只有對應數位都是 0,所得結果才是 0;反之,就是 1。
按位或運算的運算法則如表 4 所示。
| 第一個操作數 | 第二個操作數 | 結果位的值 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
例如,在 Python 交互式解釋器上計算 4 | 8 的值,執行過程如下:
>>> 4 | 8
12
計算過程如圖 5 所示。
圖 5 4 | 8 的計算過程
^按位異或運算符
按位異或運算的運算符是 ^,它有 2 個操作數,運算法則是,按位將 2 個操作數對應的二進制數一一對應,當對應位的二進制值相同(同為 0 或同為 1)時,所得結果為 0;反之,則為 1。
^ 運算符的運算法則如表 6 所示。
| 第一個操作數 | 第二個操作數 | 結果位的值 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
例如,在 Python 交互式解釋器中,計算 31 ^ 22 的值,其執行過程為:
>>> 31 ^ 22
9
計算過程如圖 7所示。
圖 7 31^22的計算過程
~按位取反運算符
按位取反,也常稱為“按位非”運算,此運算的運算符為 ~,它只有 1 個操作數,其運算法則為:將操作數的所有二進制位,1 改為 0,0 改為 1。
例如,使用 Python 交互式解釋器計算 -5 取反后的結果,其執行過程為:
>>> ~-5
4
注意,此運算過程涉及與計算機存儲相關的內容,首先需要了解什么是原碼、反碼以及補碼:
- 原碼是直接將一個數值換算成二進制數。有符號整數的最高位是符號位,符號位為 0 代表正數,符號位為 1 代表負數。無符號整數則沒有符號位,因此無符號整數只能表示 0 和正數。
- 反碼的計算規則是:對原碼按位取反,只是最高位(符號位)保持不變。
- 補碼的計算規則是:正數的補碼和原碼完全相同,負數的補碼是其反碼 +1;
其實,所有數值在計算機底層都是以二進制形式存在的,為了方便計算,計算機底層以補碼的形式保存所有的整數(如圖 8 所示):
通過圖 8 可以得出,按位取反運算,實際上就是對存儲在計算機底層中,以補碼形式存儲的整數進行按位取反所得的最終值。
注意,本節涉及到的所有按位運算符,操作的二進制數,都是操作數的補碼形式。
<<左移運算符
左移運算符是將操作數補碼形式的二進制數,整體左移指定位數,左移后,左邊溢出的位直接丟棄,右邊空出來的位以 0 來填充。例如如下代碼:
>>> 5 << 2
20
>>>-5 << 2
-20
圖 9 示范了 -5 左移兩位的運算過程。
圖 9 -5 左移兩位的運算過程
在圖 5 中,上面的 32 位數是 -5 的補碼,左移兩位后得到一個二進制補碼,這個二進制補碼的最高位是 1,表明是一個負數,換算成十進制數就是 -20。
>>右移運算符
Python 的右移運算符為 >>,其運行法則是,把操作數補碼形式的二進制右移指定位數后,左邊空出來的位以符號位來填充,右側溢出位直接丟棄。
請看下面代碼:
>>> -5 >> 2
-2
圖 10 給出了-5 >> 2 的運算過程。
圖 10 -5>>2 的運算過程
從圖 10 來看,-5 右移兩位后左邊空出兩位,空出來的兩位以符號位來填充,右邊溢出的兩位被直接丟棄。因此,右移運算后得到的結果的正負與第一個操作數的正負相同。右移后的結果依然是一個負數,我們知道,這是一個負數的補碼(負數的補碼和原碼不同),換算成十進制數就是 -2。
必須指出的是,無論是左移運算符還是右移運算符,它們都只適合對整型數進行運算。
在進行位移運算時,不難發現,左移 n 位就相當於來以 2 的 n 次方,右移 n 位則相當於除以 2 的 n 次方(如果不能整除,實際返回的結果是小於除得結果數值的最大整數的)。不僅如此,進行位移運算只是得到了一個新的運算結果,而原來的操作數本身是不會改變的。
