如果给出两个整数a和b,让你写一个方法来计算a与b的和,你首先会想到什么方法呢?
我想大多数人会直接如下处理:
我们都知道,计算机中的加减法是以二进制数来参与运算的。例如令a=3,b=5,则a+b在计算机中如下表示:
0000 0011
+
0000 0101
=
0000 1000
0000 1000换算为十进制数就是8,这样表示当然没有问题,但还有没有其他解决方法呢?
位运算是一个很好的示范。
a^b如下表示:
0000 0011
^
0000 0101
=
0000 0110
十进制数为6,可以看出a^b运算时没有进位变化
a&b如下表示:
0000 0011
&
0000 0101
=
0000 0001
十进制数为1,可代表a+b实际运算中的进位
将a^b的二进制数0000 0110与a&b的二进制数0000 0001相联系,与a+b的进制数0000 1000作比较可以发现一些规律:
进位0000 0001在实际运算中需要进一位,利用左移符号就是,0000 0001<<1为0000 0010,十进制数为2,即(8=0000 1000)=(6=0000 0110)+(2=0000 0001<<1),也就是说:
0000 0110
+
0000 0001<<1
=
0000 1000
即
a ^ b
+
(a & b)<<1
=
a+b
a^b等于a+b中无进位数相加,a&b<<1等于a+b中进位的数,所以若利用位运算符计算a+b,可采用a ^ b+(a & b)<<1的形式。
为了避免用到算术运算符,只有当(a & b)<<1即进位为0时成立。可知在进行a ^ b和(a & b)<<1运算过程中,始终存在a ^ b+(a & b)<<1=a+b,当a ^ b和(a & b)<<1持续运算时,最终会出现(a & b)<<1=0的情况(类似3+5=6+2=4+4=0+8=8+0),此时的a ^ b=a+b。如上3+5,当a^b=8,(a & b)<<1=0时,位运算成功,代码如下:
位运算在实际应用中不止如此,它还可以很方便的交换两个整数,代替传统的temp交换方式:
判断奇偶性:
x&1即x的二进制&0000 0001。如果x的二进制从右往左第一位为0,依照&性质可知x&1=0,则为偶数;如果x的二进制从右往左第一位为为1,那么x&1=1,则为奇数。
取相反数:
以2和-2为例(用byte类型换算),2的二进制数为0000 0010,反码补码相同,-2的二进制数为1000 0010,反码为1111 1101,补码为1111 1110。令x=2,那么~x为1111 1101,~x+1=1111 1110,故-x=~x+1,以x=-2亦然。
位运算符还可以用在计算绝对值、自定义取整数位等等。
单纯的利用算术运算符"+"来计算两个整数的和无疑是大众化的,利用其它方法也许更能开拓我们的思路,不过在实际应用中,时间复杂度或者空间复杂度可能是我们考虑的头等因素,位运算的效率不见得比"+"高,最重要的还是契合,要知道生活中有这么一句话:适合自己的才是最好的。
来自https://mp.weixin.qq.com/s/5VWl5taiHpSSnm8G0HUDeA