位运算
常用的位运算技巧
位运算是很多算法优化的基础和实现的条件,极其重要。理解位运算对于一些算法及其优化有着非常重要的意义。本篇随笔讲解位运算的一些基本原理和常用的使用技巧。
注:本篇随笔的所有“运算”均指二进制下的运算,请大家自行理解。
1、与(&)运算
(1)运算法则
两个二进制数进行与&运算,如果对应位都为1则结果为1,否则为0.
(2)技巧及用途
与运算常常用于二进制下的取位操作。想要知道二进制下的某位是否是1,就&上这个位数对应的十进制数。假如返回的是这个十进制数本身,则这个位的确是1,反之就是0.
比如:
我们要取第三位是否为1,我们只需要与&上第三位(二进制表示为100)对应的二进制数4,如果返回值为4,就代表第三位为1,反之就是0.
最常用的是取二进制下的最末位,即a&1。这样的技巧可以用于判断奇偶,根据二进制常识,尾数为1则为奇数,反之为偶数。
2、或(|)运算
(1)运算法则
两个二进制数进行或|运算,如果对应位有一个为1,结果就为1.只有在两个数的对应位置都是0的时候,结果才为0.
(2)技巧及用途
或运算常用于二进制特定位的赋值。想把哪个位强行变成1,就用这个数|上这个位数对应的二进制数。
还是上面那个例子,我们想让00000的第三位变成1.即十进制变4,我们直接|上4就可以。
当然,不同于&运算,我们很少用|运算进行任意位赋值。通常来讲,我们只使用a|1把a的最后一位强行变成1,其实质意义是把原数加一。或者使用a|1-1再把它变为0.这个技巧通常用于把它变成它最接近的偶数。
3、异或(^)(xor)运算
(1)运算法则
两个二进制数进行异或(^)运算,如果对应位相同,不管是0或者是1,都返回0,反之返回1.
(2)技巧及用途
其实没啥用途...
好吧,我介绍一个性质:一个数经过两次异或之后等于原数。
(很好理解)
4、非(~)运算
(1)运算法则
把给定二进制数全部取反。
(2)技巧及用途
其实没什么运算上的用途,本蒟蒻曾看见一些大佬用这个运算判断输入是否为0...
大约长这个样子:
while(~scanf("%d",&n))
5、左移(<<)运算
(1)运算法则
a<<b表示把a的二进制位向左移动b位,低位用0补上。
(2)技巧及用途
根据二进制的常识,我们会发现,二进制第k位上的数就等于 $2^k$。(从0开始计位)比如,二进制下的100就是\(2^k\)(k=2)\(=4\)。
所以我们发现,左移运算a<<b的实质就是\(a×2^b\)。
左移运算最常用的技巧就是用来代替×2的整数次幂的乘法运算。因为我们普遍认为,位运算是要比四则运算加减乘除及模运算更快一些的运算。
6、右移(>>)运算
(1)运算法则
a>>b就是把a的二进制位向右移动b位,溢出的舍去。
(2)技巧及用途
类比于左移运算,我们发现右移运算就是把a除以2的整数次幂。这就是右移运算的用途——优化除法运算。
这里需要特殊说明的是,右移算法可以用在数学知识中的求最大公约数的程序块上。因为mod运算的效率慢的出奇,所以我们可以用右移运算来进行除以2的操作。据说可以提高百分之60的效率。
7、位运算优先级
位运算的优先级是我们在处理位运算的时候常常要考虑的问题,诚然,我们可以用括号强制位运算的顺序,但是,我们还是应该学会位运算的优先级(这应该是常识)。
位运算的优先级如下:
按位反(~)>位移运算(<<,>>)>按位与(&)>按位异或(^)>按位或(|)

浙公网安备 33010602011771号