a+b

不使用加法计算a+b的值

首先考虑十进制加法中,如8+15:

1、不考虑进位:各位相加:个位得8+5=13,个位为3;十位得0+1=1;结果为13

2、考虑进位:个位进位为10

3、1和2中的结果相加得13+10=23

按照上述思想考试二进制加法中:如1000+1111

1、不考虑进位:各位相加:1+1=0,1+0=1,0+1=1,0+0=0,与位运算中的亦或操作相同 a^b

2、考虑进位:显然只有1+1会出现进位,相对于这位的进位为10,即把与运算的结果往左移一位 (a&b)<<1

3、1和2中的结果相加直到不产生进位

以上分析来自lintCode

根据以上分析,我们可以得出一个结论:a+b = f(a+b) + m(a+b)
其中f(a+b)表示无进位的a+b,比如上面的13,m(a+b)表示进位结果,比如上面的10

在位运算中,异或运算通常也叫做无进位的加法,与运算刚好可以用来计算进位结果(因为只有 1&1 == 1,只有 1 + 1 会进位),所以我们又可以得出以下公式:a+b = a^b + (a&b)<<1,由于不能用加法,这个公式我们可以很容易的用递归实现:

int sum(int a, int b)
{
    if (b == 0) {
        return a;
    }
    int c = a^b;
    int d = (a&b)<<1;
    return sum(c, d);
}

非递归版本
前有公式:a+b = a^b + (a&b)<<1,其中 a 对应于 a^b ,b 对应于 (a&b)<<1,因为 ^ 在这里是加法,所以 a 代表无进位加法结果,b 代表进位信息,当没有进位信息时(b==0),计算结束,据此,我们可以写出如下非递归代码:

int sum(int a,int b)
{
    /**
     先计算进位结果 c
     然后计算无进位结果 a
     如果有进位,设置给b,进入下一次计算
     */
    while (b != 0) {
        int c = (a&b)<<1;
        a = a^b;
        b = c;
    }
    return a;
}

PS:对于递归运算,千万不要试图用大脑来计算每一次递归的结果!!!

你可能感兴趣的:(a+b)