看到了这个题
实际是利用位运算实现两个整数的加法运算
int Add(int a,int b)
{
if(b == 0) return a;
int sun,carry;
sum = a^b; //完成第1步无进位加法
caryy = (a&b)<<1; //完成第2步有进位的加法,并进位
return Add(sum,carry); //进行递归相加
}
x = (x&y) + ((x^y)&x)
y = (x&y) + ((x^y)&y)
((x^y)&x) + ((x^y)&y) = x^y
x + y = 2 * (x&y) + (x^y)
二进制位移操作。当 x 为 1 时,1 转为二进制还是 1,向左位移变为 10,然后与 1 进行二进制或运算就是 11,二进制 11 其实就是十进制的 3。
1 << 1 等于 00000001 << 1 等于 00000010 等于十进制 2
2 << 1 等于 00000010 << 1 等于 00000100 等于十进制 4
3 << 1 等于 00000011 << 1 等于 00000110 等于十进制 6
4 << 1 等于 00000100 << 1 等于 00001000 等于十进制 8
也不难理解向左移动多位。如向左移 2 位 00001110 << 2。
另外:
((x&y)+((x^y)>>1)是用来求x和y的平均数的,即(x+y)/2.
分析如下:
(x&y)+((x^y)>>1),把x和y里对应的每一位(指二进制位)都分成三类,每一类分别计算平均值,最后汇总。
其中,一类是x,y对应位都是1,用x&y计算其平均值;
一类是x,y中对应位有且只有一位是1,用(x^y)>>1计算其平均值;
还有一另是x,y中对应位均为0,无须计算。
下面分别说明一下前两种情况是怎样计算的:
x,y对应位均为1,相加后再除以2还是原来的数,如两个00001111相加后除以2仍得00001111,这是第一部分。
第二部分,对应位有且只有一位为1,用“异或”运算提取出来,然后>>1(右移一位,相当于除以2),即到到第二部分的平均值。
第三部分,对应位均为零,因为相加后再除以二还是0,所以不用计算。
三部分汇总之后就是(x&y)+((x^y)>>1)
顺便解释一下前面说到可以避免溢出。假设x,y均为unsigned char型数据(0255,占用一字节),显然,x,y的平均数也在0255之间,但如果直接x+y可能会使结果大于255,这就产生溢出,虽然最终结果在255之内,但过程中需要额外处理溢出的那一位,在汇编中就需要考虑这种高位溢出的情况,如果(x&y)+((x^y)>>1)计算则不会。