1. 程式人生 > >python學習05:Python位運算子詳解

python學習05:Python位運算子詳解

位運算子通常在圖形、影象處理和建立裝置驅動等底層開發中使用。使用位運算子可以直接運算元值的原始 bit 位,尤其是在使用自定義的協議進行通訊時,使用位運算子對原始資料進行編碼和解碼也非常有效。

位運算子對於初學者來說有些難度,因此初學者可先跳過本節內容。

位運算子的操作物件是整數型別,它會把數字看做對應的二進位制數來進行計算。 Python 支援的位運算子如表 1 所示。
  表 1 Python位運算子
位運算子 說 明 使用形式 舉 例
& 按位與 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 所示。
  表 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 所示。
  表 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 所示。
  表 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 次方(如果不能整除,實際返回的結果是小於除得結果數值的最大整數的)。不僅如此,進行位移運算只是得到了一個新的運算結果,而原來的運算元本身是不