位运算
电脑中的器件都是基于二进制的,所以会产生一系列和二进制有关的运算
1.与
对于两个数字(都是 0
或者 1
)
只有两个数字都为 1
时,相与的结果才为 1
,否则为 0
。
与运算用 and
或者符号 &
来表示。
cpp
0 and 0 = 0
0 and 1 = 0
1 and 0 = 0
1 and 1 = 1
1
2
3
4
2
3
4
2.或
对于两个数字(都是 0
或者 1
)
只要一个数字为 1
时,相或的结果为 1
,否则为 0
。
与运算用 or
或者符号 |
来表示。
cpp
0 or 0 = 0
0 or 1 = 1
1 or 0 = 1
1 or 1 = 1
1
2
3
4
2
3
4
3.异或
对于两个数字(都是 0
或者 1
)
当数字为相同时,异或的结果为 0
,否则为 1
。
与运算用 xor
或者符号 ^
来表示。
cpp
0 xor 0 = 0
0 xor 1 = 1
1 xor 0 = 1
1 xor 1 = 0
1
2
3
4
2
3
4
4.非
对于两个数字(都是 0
或者 1
)
将数字取非等于把数字反转
非运算用符号 !
来表示
cpp
!0 = 1
!1 = 0
1
2
2
5.按位操作
对于两个整数来说,进行与、或、异或操作,相当于先把这两个数字变成二进制数字,然后对应每一位分别进行与、或、异或操作,然后再化为十进制数字
cpp
3 and 5 = 0011 and 0101 = 0001 = 1
3 or 5 = 0011 or 0101 = 0111 = 7
3 xor 5 = 0011 xor 0101 = 0110 = 6
1
2
3
2
3
其中按位操作还有一个取反操作:
对于一个数据类型,比如 short
它一共有16位,按位取反则就将该数字的二进制每一位都变为原来相反的数字,用符号~
表示
cpp
~3 = ~ 0011 = 1100
1
6.左移
将一个数字左移 k
位,相当于把这个数字先化为二进制数,然后再在最后补 k
个 0
。
cpp
(5<<2) = (101<<2) = 10100 = 20
1
如果左移的过多,超出了数据类型能表示的位数,则左侧会消失。
可以看出来,左移 k
位其实和将原数字乘以
7.右移
将一个数字左移 k
位,相当于把这个数字先化为二进制数,然后将最后 k
位删掉,在前面补 k
个 0
。
cpp
(5>>2) = (101>>2) = 001 = 1
1
右移 k
位其实和将原数字除以
左右移的优先级非常低,涉及和别的运算一起写的时候一定要加括号,不加就等死吧。
8.操作一个数的二进制位
判断第 k
位是否为 1:
cpp
if((x>>k)&1);//或者
if(x&(1<<k));
1
2
2
改变第 k
为:
cpp
int b=(1<<k);
x=x|b;//将第k位设置为1
x=x^b;//将第k为取反
x=x&(x^b);//将第k位设置为0
1
2
3
4
2
3
4
P8072 [COCI2009-2010#7] COKOLADA