python學習05:Python位運算子詳解
阿新 • • 發佈:2019-10-09
位運算子通常在圖形、影象處理和建立裝置驅動等底層開發中使用。使用位運算子可以直接運算元值的原始 bit 位,尤其是在使用自定義的協議進行通訊時,使用位運算子對原始資料進行編碼和解碼也非常有效。
表 1 Python位運算子
按位與運算的運演算法則如表 2 所示。
表 2 & 運算子的運演算法則
例如,在 Python 互動式直譯器中,計算 12 & 8 的值,執行過程如下:
圖 3 12 & 8 的計算過程
按位或運算的運演算法則如表 4 所示。
表 4 | 運算子的運演算法則
例如,在 Python 互動式直譯器上計算 4 | 8 的值,執行過程如下:
圖 5 4 | 8 的計算過程
^ 運算子的運演算法則如表 6 所示。
表 6 ^ 運算子的運演算法則
例如,在 Python 互動式直譯器中,計算 31 ^ 22 的值,其執行過程為:
圖 7 31^22的計算過程
例如,使用 Python 互動式直譯器計算 -5 取反後的結果,其執行過程為:
其實,所有數值在計算機底層都是以二進位制形式存在的,為了方便計算,計算機底層以補碼的形式儲存所有的整數(如圖 8 所示):
圖 8 ~-5的運算過程( 點此檢視高清大圖)
通過圖 8 可以得出,按位取反運算,實際上就是對儲存在計算機底層中,以補碼形式儲存的整數進行按位取反所得的最終值。
圖 9 -5 左移兩位的運算過程
在圖 5 中,上面的 32 位數是 -5 的補碼,左移兩位後得到一個二進位制補碼,這個二進位制補碼的最高位是 1,表明是一個負數,換算成十進位制數就是 -20。
請看下面程式碼:
圖 10 -5>>2 的運算過程
從圖 10 來看,-5 右移兩位後左邊空出兩位,空出來的兩位以符號位來填充,右邊溢位的兩位被直接丟棄。因此,右移運算後得到的結果的正負與第一個運算元的正負相同。右移後的結果依然是一個負數,我們知道,這是一個負數的補碼(負數的補碼和原碼不同),換算成十進位制數就是 -2。
必須指出的是,無論是左移運算子還是右移運算子,它們都只適合對整型數進行運算。
位運算子對於初學者來說有些難度,因此初學者可先跳過本節內容。
位運算子的操作物件是整數型別,它會把數字看做對應的二進位制數來進行計算。 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 ~-5的運算過程( 點此檢視高清大圖)
通過圖 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 次方(如果不能整除,實際返回的結果是小於除得結果數值的最大整數的)。不僅如此,進行位移運算只是得到了一個新的運算結果,而原來的運算元本身是不