About Bit Manipulation (Bit-Twiddling)
位运算
常用 trick
- 学会用 bitset
x & 1
检测 x 是否为奇x & (x-1)
可以检测是否是2的整数次幂 (x&x-1 可以清除最右边的1,如果这个1是第一位的1, 那这个数就变为0)x & 0xaaaaaaaa
判断 1 是不是都在偶数上,结合x & x - 1
可以判断 4 的幂x & 0x55555555 > 0
也可以判断 1 是不是在偶数,这个可以自己设计,可以变动的- 在golang里 貌似 x - 1 不加括号结果是错的
(x >> i) & 1
取出 x 的第 i 位二进制
基础知识
Binary,Octal和 Hexadecimal的表示 (通用)
- Binary:
0b
- Octal:
0 or 0o
(Python和JS允许0o) - Hexadecimal:
0x or 0X
运算符,运算符顺序
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与操作,按二进制位进行”与”运算。 运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1; |
(A & B) 将得到 12,即为 0000 1100 |
| | 按位或运算符,按二进制位进行”或”运算。 运算规则:`0 | 0=0; 0 |
^ | 异或运算符,按二进制位进行”异或”运算。 运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0; |
(A ^ B) 将得到 49,即为 0011 0001 |
~ | 取反运算符,按二进制位进行”取反”运算。 运算规则:~1=-2; ~0=1; |
(~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。 |
<< | 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0) | A << 2 将得到 240,即为 1111 0000 |
>> | 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 | A >> 2 将得到 15,即为 0000 1111 |
位运算的赋值运算符
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
---|---|---|
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
其他运算符
运算符 | 描述 |
---|---|
sizeof | sizeof 运算符返回变量的大小。例如,sizeof(a) 将返回 4,其中 a 是整数。 |
Condition ? X : Y | 条件运算符。如果 Condition 为真 ? 则值为 X : 否则值为 Y。 |
, | 逗号运算符会顺序执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值。 |
.(点)和 ->(箭头) | 成员运算符用于引用类、结构和共用体的成员。 |
Cast | 强制转换运算符把一种数据类型转换为另一种数据类型。例如,int(2.2000) 将返回 2。 |
& | 指针运算符 & 返回变量的地址。例如 &a; 将给出变量的实际地址。 |
* | 指针运算符 * 指向一个变量。例如,*var; 将指向变量 var。 |
运算符优先级 「由高到低」
类别 | 运算符 | 结合性 |
---|---|---|
后缀 | () [] -> . ++ - - | 从左到右 |
一元 | + - ! ~ ++ - - (type)* & sizeof | 从右到左 |
乘除 | * / % | 从左到右 |
加减 | + - | 从左到右 |
移位 | << >> | 从左到右 |
关系 | < <= > >= | 从左到右 |
相等 | == != | 从左到右 |
位与 AND | & | 从左到右 |
位异或 XOR | ^ | 从左到右 |
位或 OR | | | 从左到右 |
逻辑与 AND | && | 从左到右 |
逻辑或 OR | || | 从左到右 |
条件 | ?: | 从右到左 |
赋值 | = += -= *= /= %=>>= <<= &= ^= |= | 从右到左 |
逗号 | , | 从左到右 |
1 |
|
190. 颠倒二进制位 「>>= 和 >> 的区别」
1 |
|
XOR 的性质:
x⊕x=0 , x⊕0 = x
x⊕y=y⊕x (交换律)
(x⊕y)⊕z=x⊕(y⊕z) (结合律) 「不支持分配律」
x⊕y⊕y=x (自反性)
∀i∈Z,有 4i⊕(4i+1)⊕(4i+2)⊕(4i+3)=0
如何取按照要求 取一个整型中的某些二进制位?
对于x , 取其第i位的二进制 $\rightarrow$ (x >> i) & 1 (从0开始)
对于x,清除第 i 位的二进制
如果我们框定了x的范围,比如我们确认x <= 1024 那么32位中必然只需要使用其中最右边的10位
- 想取 高4位(即10位中左边的4位) 那显然 res = x >> 6
- 想取 低6位 则不需要移位,可以通过==与运算(和全1与)==直接取 比如这里 2^6 -1 res = x & 63;
关于进制转换问题
- 我们使用的进制转换是短除法的进制转换,因此最后有一个 reverse 操作,不要忘记
交换x y
- 直接交换法: a = a - b , b = a + b, a = b - a;
- 异或法 : x = x ^ y, y = x ^ y, x = x ^ y
__builtin_popcount(i) 计算32位整型里 1的个数
- 一句话逻辑运算
- or => 只要有 1 结果为 1
- and => 只有 1 & 1 = 1,其他为 0
- 取奇偶(配合移位取二进制)
- 分组(见
找出 2 个只出现 1 次的数
, 核心思想:按照某一位是否为 1 来把数组分成两个部分)
- xor => 两个二进制不同, 结果为 1 / 二进制不进位加法
- 抵消 / 二进制交换
About Bit Manipulation (Bit-Twiddling)
https://www.mementos.top/1976/04/01/about Bit Manipulation/