int function(int x,int y)
{
return ((x&y) + ( (x^y)>>1 ));
}
请看上面的一段函数,输入两个整数x和y,返回x&y + (x^y)>>1。大家是否看出来这段函数是做什么的呢?因为我自己刚开始没有太明白哈,所以在学习理解之后,再给大家分享一遍,如果大家都知道,欢迎大家提出不同的意见。
大家都知道在计算机中,数值都是以二进制的形式进行存储的,在运算时也都是以二进制的形式进行运算的。
首先回顾一下Java位运算符的基础知识,位运算符是先将操作数转为二进制数,然后按位进行运算,常见的几种位运算符:
&:按位与运算符。 同1则1,有0即0。
|:按位或运算符。 同0则0,有1即1。
^:按位异或运算符。同1则0,一1即1。
>>:位移运算符,>>x 表示向右移x位
先随便找两个数值带入试一下。观察函数的计算结果,比如:
x = 5 = 0101
y = 7 = 0111
x & y = 0101 = 5
(x ^ y)>>1 = 0010 = 2 >>1 = 0001 = 1
(x & y + (x ^ y)>>1) = 5 + 1 = 6
大家会发现计算出的结果好像是平均值,即(x + y)/ 2。为什么这样使用位运算符会达到求平均值的目的呢?因为位运算符是基于每一位进行操作的,根据这个思路,我们反推一下就会想到:是否可以把操作数的每一位都拆分一下呢,就以上面的x=5,y=7为例:
x = 5 = 0101 = 0000 + 0100 + 0000 + 0001
y = 7 = 0111 = 0000 + 0100 + 0010 + 0001
当我们把操作数拆分为各位上数值之和后,仔细观察操作数,发现运算时只会有两种情况,要么是1和1,要么是0和1。如果是1和1说明两个操作数某一位的数值是相同的,而x&y的结果是1,这样就等同于(x + y)/2。
如果是0和1,则说明这一位上,只有一个操作数有值,而x^y说明是取这一位上有值的那个操作数,然后>>1,说明有值的那个数需要除以2,相当于同一位置上数值不同的数求和后求平均值。
当拆分后的对应的各个位置上的数求和、求平均值之后,再将其运算结果加起来,是不是就是原操作数求和之后求平均值呢?
所以((x&y) + ( (x^y)>>1 )) = (x + y)/2