灵活运用位操作往往能使程序效率得到很大的提高,为了能灵活的使用位操作还是很有必要熟记一些位操作小技巧:

1.判断奇偶

奇数一定能写成偶数+1,而这个+1就对应了2进制中最右边的那一位,所以只要判断最右边的位是否是1就可以判断奇偶,使用位操作如下:

返回1则为奇数,返回0为偶数

2.变换符号

无论正负数,只需要取反加一即可:

与上式等价的操作:

由于计算机中用补码表示负数,负数补码变原码是除符号位以外取反加1,连符号位也一起改之后,当然只是变了个符号。另一种思考方式:为什么无论对正数还是负数而言都是取反加一呢?一张图解决你的疑惑:

11

对补码而言,1000并不是像原码那样表示为0,而是表示最小负整数,这也就造成正负不对称:4bits整数的范围为[-8,7],负数能多表示一个数,从上图可以看出,无论是正负数,取反之后都偏移了,+1修正偏移后就能求出相反数。

3.判断x是否为0

当然,前提是不能使用==。这时候就需要用到上面所说到的补码数据表示,补码表示法中的0十分特殊,因为它没有与其“对称”的数并且0的符号位只能为0(全0),而非0 的数要么其符号位为1,要么它的相反数的符号位为1,根据这个特点就能用位操作来判断数字是否为0: 首先根据上述原理判断符号位:

将符号位移动到最右边并测试该位是否为1:

若为1说明不是0,不为1说明该数是0,用异或来返回判断结果(非0返回0):

4.用^交换两数

这个方法太经典了,就不多说了:

5.判断两整数的大小

规则如下:

共有两种情况,1.x、y同号;2.x、y异号 ;异号的情况比较简单,只需要判断其中一个数的正负即可。对于同号的情况,由于x、y都为整数,所以可以将小于等于转换成小于号: dd   具体如下:

其中s_x^s_y是判断符号位是否相同,(s_x^s_y)&s_y 表示符号位不同且y是负数,那么x肯定更大,则返回1;(!(s_x^s_y))&(!s_x_y_1) 这句话表示符号位相同且x-y-1<0则返回0.

 6.异或的妙用

主要考察两种特殊情况:与全0异或、与全1异或 与全0异或相当于不变:

与全1异或相当于取反:

知道这个之后再来看看如何巧用异或来求绝对值:

a^x : 若x为负数,则a为全1,效果相当于取反;若x为正数,则a为全0,效果相当于不变;

a&1 : 若x为 负数,其绝对值为取反加1;若x为正数,其绝对值不变。

 7.符号位的妙用

对于有符号整数而言,其最高位是符号位,结合位操作能使符号位拥有很奇妙的用处比如:

若x为正整数,那么nsign就是一个32位全为0的数,若x为负数,那么nsign则是一个32位全为1的数;这种操作有时候能够替代if else分支:

可以变为一句话:

不得不感叹,计算机背后永远离不开数学,是数学让计算机变得更加美丽!

8.逻辑右移算掩码

逻辑右移有个十分特殊的特定:“复制”符号位。通过逻辑右移操作能很方便的生成计算机网络中的子网掩码,比如要生成一个子网掩码255.255.255.0,只需一句话:

先将1移动到符号位,再用逻辑右移复制符号位即可。

观看更多有关 的文章?

*

+
跳转到评论