进制与位运算

进制

0b为二进制的前缀标识,0为八进制的前缀标识,0x为十六进制的前缀标识,十进制没有前缀标识。
\((0xaaaaaaaa)_{16}\) = 10101010101010101010101010101010 (偶数位为1,奇数位为0)
\((0x55555555)_{16}\) = (0)1010101010101010101010101010101 (偶数位为0,奇数位为1)
\((0x33333333)_{16}\) = (00)110011001100110011001100110011 (1和0每隔两位交替出现)
\((0xcccccccc)_{16}\) = 11001100110011001100110011001100 (0和1每隔两位交替出现)
\((0x0f0f0f0f)_{16}\) = (0000)1111000011110000111100001111 (1和0每隔四位交替出现)
\((0xf0f0f0f0)_{16}\) = 11110000111100001111000011110000 (0和1每隔四位交替出现)

位运算

0s 表示一串 0,1s 表示一串 1。

x ^ 0s = x      x & 0s = 0      x | 0s = x
x ^ 1s = ~x     x & 1s = x      x | 1s = 1s
x ^ x = 0       x & x = x       x | x = x

利用 x ^ 1s = ~x 的特点,可以将一个数的位级表示翻转;利用 x ^ x = 0 的特点,可以将三个数中重复的两个数去除,只留下另一个数。
1^1^2 = 2
利用 x & 0s = 0 和 x & 1s = x 的特点,可以实现掩码操作。一个数 num 与 mask:00111100 进行位与操作,只保留 num 中与 mask 的 1 部分相对应的位。

01011011 &
00111100
--------
00011000

利用 x | 0s = x 和 x | 1s = 1s 的特点,可以实现设值操作。一个数 num 与 mask:00111100 进行位或操作,将 num 中与 mask 的 1 部分相对应的位都设置为 1。

01011011 |
00111100
--------
01111111

mask 计算
要获取 111111111,将 0 取反即可,~0。
要得到只有第 i 位为 1 的 mask,将 1 向左移动 i-1 位即可,1<<(i-1) 。例如 1<<4 得到只有第 5 位为 1 的 mask :00010000。
要得到 1 到 i 位为 1 的 mask,(1<<i)-1 即可,例如将 (1<<4)-1 = 00010000-1 = 00001111
要得到 1 到 i 位为 0 的 mask,只需将 1 到 i 位为 1 的 mask 取反,即 ~((1<<i)-1)。

技巧

  1. n&(n-1) 去除 n 的位级表示中最低的那一位 1。例如对于二进制表示 01011011,减去 1 得到 01011010,这两个数相与得到 01011010。
01011011 &
01011010
--------
01011010
  1. n&(-n) 得到 n 的位级表示中最低的那一位 1。-n 得到 n 的反码加 1,也就是 -n=~n+1。例如对于二进制表示 10110100,-n 得到 01001100,相与得到 00000100。
10110100 &
01001100
--------
00000100

n-(n&(-n)) 则可以去除 n 的位级表示中最低的那一位 1,和 n&(n-1) 效果一样。

posted @ 2022-05-12 11:08  Vonos  阅读(478)  评论(0)    收藏  举报