位运算相关总结
原码、反码、补码
原码
最高位是符号位,0代表正数,1代表负数,非符号位为该数字绝对值的二进制。
5:0101
-5:1101
反码
正数的反码与原码一致,负数的反码是对原码按位取反,只是最高位(符号位)不变。
5:0101
-5:1010
补码
正数的补码与原码一致,负数的补码是对原码按位取反加1,符号位不变。
5:0101
-5:1011
补码转原码
正数的补码与原码一致,负数的补码 按位取反加1,符号位不变。
反码转原码
正数的反码与原码一致, 负数的补码按位取反,符号位不变。
0的问题
用4位二进制原码表示0:-0=1000 +0=0000
用4位二进制反码表示0:-0=1111 +0=0000
用4位二进制补码表示0:-0=0000 +0=0000
表示范围
n+1位数字,绝对值最大的原码是 -(2^n - 1)和 2^n - 1
n+1位数字,绝对值最大的反码是 -(2^n - 1) 和 2^n - 1
n+1位数字,绝对值最大的补码是 -2^n
~ 取反运算符的含义
概念
~表示非运算符,就是将该数的所有二进制位全取反。
e.g.,(~10) 由于计算机中数据是以补码的形式存储的,所以01010全取反是10101(只是补码形式,还需要转成原码)。
此时得到的10101只是补码,我们需要将它先转为反码,反码 = 补码-1,得到反码为10100。
我们得到反码后,将它转为原码,原码 = 反码符号位不变,其它位全取反,得到最终的原码为11011,转化为十进制就是-11。
核心公式
(~x)=-(x+1)
位运算技巧
n & (n - 1)
其中 & 表示按位与运算。 该位运算技巧可以直接将 n 二进制表示的最低位 1 移除。 它的原理如下:
假设 n 的二进制表示为 (a10...0),其中 a 表示若干个高位,1 表示最低位的那个 1,00...0 表示后面的若干个 0,那么 n−1 的二进制表示为:(a01...1)
我们将 (a10...0)与(a01...1)进行按位与运算,高位 a 不变,在这之后的所有位都会变为 0,这样我们就将最低位的那个 1 移除了。
n & (-n)
其中 -n 是 n 的相反数,是一个负数。 该位运算技巧可以直接获取 n 二进制表示的最低位的 1。
由于负数是按照补码规则在计算机中存储的,−n 的二进制表示为 n 的二进制表示的每一位取反再加上 1,因此它的原理如下:
假设 nn 的二进制表示为 (a10...0)
,其中 a 表示若干个高位,1 表示最低位的那个 1,00...0 表示后面的若干个 0,那么 −n 的二进制表示为:(~a10...0)。其中 ~a 表示将 a 每一位取反。我们将 (a10...0)与(~a10...0) 进行按位与运算,高位全部变为 0,最低位的 1 以及之后的所有 0 不变,这样我们就获取了 n 二进制表示的最低位的 1。
应用
判断2的幂
如果 n 是正整数并且 n & (n - 1) = 0,那么 n 就是 2 的幂。
如果 n 是正整数并且 n & (-n) = n,那么 n 就是 2 的幂。
统计二进制中1的个数
不调用库:
a=5
t=0
while a:
t+=1
a-=a&(-a)
print(t) #2
调用bit_count() (python3.10版本新函数)
n=19
bin(n) #0b10011
n.bit_count() #3
#相当于:
bin(n).count('1') #3

浙公网安备 33010602011771号