Python-位操作( &、 | 、^、~ 、>>、 <<)
用于提高运算速度,规避算术运算符。
在位操作运算中,不应该试图考虑先得到一个数的二进制码,而应该将这个数看作是一个二进制码,二进制补码与整数之间是一一对应的。诚然 Python语言中有内置函数 bin将一个整数转换为二进制,Python中使用该函数转换为负数并不是其补码。因此不能先得到该数的二进制码。同时绞尽脑汁得到一个数的二进制补码是没有必要的。
&:按位与操作,只有 1 &1 为1,其他情况为0。可用于进位运算。
|:按位或操作,只有 0|0为0,其他情况为1。
~:逐位取反。
^:异或,相同为0,相异为1。可用于加操作(不包括进位项)。
<<:左移操作,2的幂相关
>>:右移操作,2的幂相关
判断一个整数的二进制补码中 1 的个数:
既然一个整数在计算机内部为二进制的补码,那么直接对整数进行位操作即可,没有必要进行进制的转换。
1)将整数通过移位并与1进行与操作,即可判断当时末尾是否为1.但是由于整数以二进制补码的方式存储,正数右移与负数右移得到的效果并不相同,负数在右移过程中会自动补 1 .由于在c 或c++这种语言中数据的类型要先声明,如 int为32位,而在python中,由于动态语言的特性,数据的位数理想上是不受限制的,因此可通过 移位的次数进行判断,int型数据移位不能超过32即可,这样程序的循环次数恒定为32.
1 class Solution: 2 def NumberOf1(self, n): 3 # write code here 4 m = 0 5 result = 0 6 7 while m < 32: 8 if n & 1: 9 result += 1 10 n = n >> 1 11 m += 1 12 return result
2):同样的,可以通过左移 1 再与输入值进行与操作进行判断。仍然是由于Python不会存在溢出现象,因此需要用到 数据类型的位数,进行限制。
1 class Solution(): 2 def getResult(self, n): 3 m = 1 4 result = 0 5 i = 0 6 7 while i < 32: 8 i += 1 9 if m&n : 10 result += 1 11 m = m << 1 12 return result
3)一个二进制减一再于自身与操作能够将最后一位1置零。如 1011-1 = 1010 1010&1011 = 1010、1010-1 = 1001 1001 & 1010 = 1000、1000-1 = 0111 0111 &1000 = 0000
但是,Python不会溢出,因此负数在进行持续减一 的运算,若通过当前值是否为0进行循环终止条件会导致死循环。因此需要为正负数分别设定终止条件。
1 class Solution2(): 2 def getResult(self, n): 3 result = 0 4 if n >= 0: 5 while n: 6 result += 1 7 n = (n - 1)&n 8 else: 9 while n >= -2147483648: 10 result += 1 11 n = (n - 1)&n 12 return result
4):一个负数必然对应一个正数,先通过加法运算得到负数的相反数,这样可以将负数当作正数进行操作,唯一不同的是,负数的符号位要多一个 1
1 # -*- coding:utf-8 -*- 2 class Solution: 3 def NumberOf1(self, n): 4 # write code here 5 result = 0 6 7 if n < 0: 8 n = n + (1<<31) 9 result += 1 10 result += bin(n)[2:].count('1') 11 return result
5):结合方法 4 与 3之前的方法:
1 # -*- coding:utf-8 -*- 2 class Solution: 3 def NumberOf1(self, n): 4 # write code here 5 result = 0 6 7 if n < 0: 8 n = n + (1<<31) 9 result += 1 10 while n: 11 result += 1 12 n = n&(n-1) 13 return result