一、六种常见的“按位运算”
1.与(&)运算
运算规则:对两个整数对应的二进制位进行操作,当两个相应的二进制位都为1时,该位的结果才为1,否则为0。
a=5 #0101 | |
b=7 #0111 | |
print(a&b) | |
#a&b=0101 | |
#输出对应的十进制数:5 |
2.或(|)运算
运算规则:只要两个相应二进制位中有一个为1,该位的结果就为1。
a=5 #0101 | |
b=7 #011 | |
print(a|b) | |
#a|b=0111 | |
#输出对应的十进制数:7 |
3.异或(^)运算
运算规则:当两个相应二进制位不同时,该位结果为1;相同时,该位结果为0。
a=5 #0101 | |
b=7 #0111 | |
print(a^b) | |
#a^b=0010 | |
#输出对应的十进制数:2 |
4.取反(~)运算
运算规则:对一个整数的二进制位进行取反操作,0变为1,1变为0。
tips:不过要注意其在计算机中的表示是基于补码形式的,比如~5(原码00000101,补码00000101),取反后的补码为11111010,对应的原码为10000110,即十进制的-6。
ps:原码:二进制表示,最高位为符号位,正数的符号位为 0,负数的符号位为 1,其余位表示数值的绝对值。补码:也是一种二进制表示形式,正数的补码和原码相同,负数的补码是其原码除符号位外各位取反,然后在最低位加 1 得到的。
a=5 #八位二进制的原码:0000 0101 | |
print(~a) | |
#a的补码为原码本身0000 0101 | |
#~a=1111 1010(这是取反后的补码)对应原码为1000 0110 再对应十进制为-6 | |
#输出对应的十进制数:-6 |
5.左移(<<)运算
运算规则:将一个整数的二进制位向左移动指定的位数,右边空出的位补0,相当于乘以2的移动位数次方。
a=5 #0101 | |
print(a<<2) | |
#左移两位:0001 0100 | |
#输出对应的十进制数:20 |
6.右移(>>)运算
运算规则:把一个整数的二进制位向右移动指定的位数。如果是无符号数,左边空出的位补0,相当于除以2的移动位数次方。
b=8 #1000 | |
print(b>>2) | |
#左移两位:0010 | |
#输出对应的十进制数:2 |
二、按位运算在算法中的运用思维
1.求最小偶倍数:
通解:辗转相除法
class Solution: | |
def smallestEvenMultiple(self, n: int) -> int: | |
a,b=n,2 | |
while b: | |
a,b=b,a%b | |
return 2*n//a |
按位运算:移位、与运算(根据题意,当 n 为奇数时,答案为 2n,当 n 为偶数时,答案为 n。)
class Solution: | |
def smallestEvenMultiple(self, n: int) -> int: | |
return n << (n & 1)#(n&1):根据与运算,当n为偶数时运算得0不移位,奇数运算得1,移动一位即X2 |
2.判断幂数
通解:用该数一直除以2,除到最后剩1则为true。
class Solution: | |
def isPowerOfTwo(self, n: int) -> bool: | |
while n>0 and n%2==0: | |
n//=2 | |
return n==1 |
按位运算法:
据此得出
class Solution: | |
def isPowerOfTwo(self, n: int) -> bool: | |
return n > 0 and n & (n - 1) == 0 |