4.3 位运算
在计算机中,程序中的所有数值都是以一位、一位的二进制数的形式储存的。为了方便计算,Python还提供了位运算。位运算是指直接按照数值的二进制形式进行运算。位运算包括位逻辑运算和移位运算。
4.3.1 位逻辑运算
位逻辑运算是指对二进制数的每一位进行数值运算。Python的位逻辑运算包含四种,分别为位与运算、位或运算、异或运算和取反运算。
1. 位与运算
Python的位与运算使用连接符(&)表示。它可以将两个二进制数的每一位都进行运算。如果相同位的数都为1,则对应的结果位也为1;若有一个不为1,则为0。位与运算如图4.13所示。
图4.13 位与运算
位与运算通常用于二进制数的取位操作,判断一个二进制数指定位的数值是否为1。运算时,需要借助另一个二进制数,该数被称为辅助二进制数。辅助二进制数是程序员自己设定的。设定原则是,判断二进制数的哪一位,就将辅助二进制数的该位设定为1,其余设定为0。
【实例4-22】现在有一个8位二进制数0b11001010,判断该二进制数的第2位和第5位的值是否为1。
(1)将辅助二进制数设定为0b01001000。判断结果如图4.14所示。其中,位与运算得出的二进制数为0b01001000。
图4.14 判断结果
(2)验证时,将得出的结果与辅助二进制数进行比较。如果两个二进制数相等,则表示指定位的数值都为1,如果不相等,则指定位的数值不全为1。进行比较代码如下:
执行后输出比较结果,如下:
输出信息表示两个二进制数的值相等,说明要判断的二进制数的第2位和第5位的值都为1。
2. 位或运算
在Python中,位或运算使用分隔符(|)表示。它可以将两个二进制数的每一位都进行运算,如果相同位有一位为1,则结果对应位就为1;反之,为0。位或运算如图4.15所示。
图4.15 位或运算
位或运算通常用于对二进制数特定位进行无条件“赋值”,即设置特定位为1。它相当于将另一个二进制数的值与原二进制数的值进行合并。
【实例4-23】现有8个房间,将每个房间看作二进制数的一位,拥有房间钥匙表示二进制数对应位的值为1,反之为0。假设,服务员A拥有房间1、4和7的钥匙,对应的二进制数为0b10010010;服务员B拥有房间2、5、6和8的钥匙,对应的二进制数为0b01001101。如果服务员A和B把钥匙给了服务员C,则服务员C拥有哪些房间的钥匙呢?下面使用位或运算来实现,如图4.16所示。图中运算后的二进制数为0b11011111,表示服务员C拥有房间1、2、4、5、6、7和8的钥匙。
图4.16 运算服务员C的二进制数
3. 异或运算
在Python中,异或运算使用次方符(^)表示。它可以将两个二进制数的每一位都进行运算。如果相同位的数值不同,则运算结果对应位为1;如果相同位的数值相同(同时为0或同时为1),则为0。异或运算如图4.17所示。
图4.17 异或运算
异或运算可用于判断二进制数的差异。
【实例4-24】文件A的二进制数为0b10100110,文件B的二进制数为0b10001100。要判断文件A和文件B是否为相同的文件,就可以使用异或进行判断,如图4.18所示。
图4.18 判断两文件是否相同
图中,异或运算得出的二进制数为0b00101010。这里需要将该二进制数与0进行比较。如果等于0,表示每一位的数值都相同,就说明两个文件相同;如果不等于0,表示二进制数至少有一位的数值不同,就说明两个文件不同。进行比较的代码如下:
执行后输出比较结果,如下:
输出信息表示两个文件不相同。
4. 取反运算
在Python中,取反运算使用波浪号(~)表示。它可以对二进制数进行取反操作。首先将二进制数加1,然后取其负值。取反运算如图4.19所示。
图4.19 取反运算
图中,二进制数为0b11100101,加1后得到二进制数0b11100110,取反运算进行取负值得出最终的二进制数为-11100110。
4.3.2 移位运算
移位运算是指将二进制数作为一个整体进行的运算。Python的移位运算包含左移运算和右移运算。
1. 左移运算
在Python中,左移运算使用“<<”表示。它可以将二进制数整体向左移动指定的位数。左移运算基本格式如下:
0bxxx表示一个二进制数;5表示将该二进制数向左移动5位。
左移运算常用于增大数值。在程序中,二进制数乘以2的操作都可以使用左移运算来代替。例如,整数202对应的二进制数为0b11001010,计算202×4的二进制数就可以通过左移运算得出,如图4.20所示。
图4.20 运算202×4
【实例4-25】下面通过代码将二进制0b11001进行左移运算,向左移动3位。代码如下:
从代码中可以看出,要移动的二进制数0b11001对应的十进制数为25,要左移3位,也就是将原来的25增大23的倍数。因此,最终得出的结果为200,对应的二进制数为0b11001000。
2. 右移运算
在Python中,右移运算使用“>>”表示。它可以将二进制数整体向右移动指定的位数。右移运算基本格式如下:
0bxxx表示一个二进制数;5表示将该二进制数向右移动5位。
右移运算常用于数据减小数值。在进行整除(//)运算时,当除以的数为2的倍数时,可以使用右移运算来代替。例如,十进制数202对应的二进制数为0b11001010,运算202//4,就相当于将202向右移动2位,如图4.21所示。
图4.21 运算202//4
【实例4-26】下面通过代码将二进制数0b1101100进行右移运算,向右移动3位。代码如下:
从代码中可以看出,要移动的二进制数0b1101100对应的十进制数为108,要右移3位,也就是将原来的108减小23的倍数。因此,最终得出的结果为13,对应的二进制数为0b1101。
4.3.3 位运算符优先级
Python进行位运算时,如果运算中存在多个位运算符,就会根据位运算符优先级的高低依次进行运算。Python支持的位运算符优先级(从高到低)如表4-2所示。
表4.2 位运算符优先级
4.3.4 位运算增强赋值
图4.22 位运算增强赋值
位运算增强赋值是指在变量的基础上,对变量的值进行位运算后再次赋值给变量。位运算增强赋值如图4.22所示。
图中,中间部分的等号(=)为赋值运算符,&、|、^、>>、<<为位运算符,它们组合在一起使用,中间没有空格。这样就可以将左侧的变量经过位运算后再次赋值给左侧变量。
【实例4-27】下面演示右移运算的增强赋值。代码如下:
说明:第一行代码将二进制数0b1001100赋值给变量a;第二行代码将变量a进行右移运算,向右移动2位,将结果再次赋值给变量a;第三行输出变量a的最终结果二进制数为0b10011。上述代码等同于以下代码: