位运算

对二进制中的每一位进行逻辑操作,而不考虑整个数的数值大小
与位运算有关的特殊数据结构如[[树状数组]]或[[01线性基]]
一般对正整数进行运算
x >>= 1与x >> 1前者修改了x,后者仅做判断。
使用位运算时尽量使用unsigned int类型,抛弃符号位。

几种位运算

按位与AND &

只有两个位都为1时,结果才为1,否则为0。
两个数字做与运算,结果不会变大。
做如下变换:

1 0 0 1 9
1 1 0 1 13
1 0 0 1 与运算结果

按位或OR |

只要两个位中有一个为1,结果就为1,否则为0。
两个数字做或运算,结果不会变小。
做如下变换:

1 0 0 1 9
1 1 0 1 13
1 1 0 1 或运算结果

按位异或XOR ^

当两个位不同时,结果位为1,否则为0。
两个数做异或运算,可能变大,也可能变小,也可能不变。
异或不会改变最大位宽,即高位全是0
交换律:x^y = y^x
结合律:x^(y^z) = (x^y)^z
自反性:x^x = 0
零元素:x^0 = x
逆运算:x^y = z,则有z^y = x(同时异或y,抵消掉,即自反性)

1 0 0 1 9
1 1 0 1 13
0 0 1 0 异或运算结果

按位取反 ~

对操作数的每一位进行取反操作,即将0变1,将1变0。
通常用于无符号整数unsigned int,避免符号位取反造成干扰。
假设只有4位

0 0 0 1 1
1 1 1 0 按位取反结果

长度不同,结果不同。

按位左移 <<

表示将一个数的二进制向左移动指定的位数。移动后低位补0。
1会移动到符号位上,所以要么使用无符号整型,要么注意不要移动到符号位。

0 0 0 1 1
1 0 0 0 按位左移3结果(9 << 3)

左移相当于对原数进行乘以2的幂次方的操作。
例如5 << 3 = 5(23)

按位右移 >>

将一个操作右移
高位补0,符号位有1不会移走,这是负数位移规则。右移相当于除以2的幂次方向下取整。
负数高位会保留1。

1 1 0 1 13
0 0 1 1 按位右移2结果(13 >> 2)

相当于13/4向下取整。

位运算技巧

判断数字奇偶

公式:x & 1;
结果为1说明是奇数,结果为0说明是偶数。
与1做与运算,高位全为0,个位为1,如果x个位也为1,与运算结果为1,x是奇数;如果x个位为0,与运算结果为0,x是偶数。

获取二进制数的某一位

公式:x >> i & 1;
结果必然为0或1,表示x的二进制表示中的第i位。

修改二进制中的某一位为1或0

公式:x | (1 << i);
将x的第i位或上1,则x[i]变为1,其他位上没有影响。
x的i位是0或1,i位或上1,一定为1。
修改为0类似用与运算,就是构造出只有第i位为0,其他位都为1的数然后做与运算。公式:x & ~(1 << i);

快速判断一个数是否为2的幂次方

公式:x & (x - 1);
如果x为2的幂次方,则x的二进制表示中只有1个,x - 1就有很多个连续的1并且和x的1没有交集,两者与运算一定为0,可证明其他情况必然不为0。

获取二进制位中最低位的1

公式:lowbit(x) = x & -x;
如果x = (010010),则lowbit(x) = (000010)
常用于数据结构[[树状数组]]中。

posted @ 2024-02-06 18:27  BreadCheese  阅读(45)  评论(0)    收藏  举报