位运算相关总结

原码、反码、补码

原码

最高位是符号位,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
posted @ 2022-07-25 12:05  岸南  阅读(50)  评论(0)    收藏  举报