LintCode第一题:A + B 问题 (位运算)c++实现

给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。

注意事项

你不需要从输入流读入数据,只需要根据aplusb的两个参数a和b,计算他们的和并返回就行。

说明

a和b都是 32位 整数么?

  • 是的

我可以使用位运算符么?

  • 当然可以
样例

如果 a=1 并且 b=2,返回3

--------------------------------------------------------------------------------------------

首先肯定要想到用位运算来操作,即用二进制来处理,好,既然想到这里,当然要举个例子来想想,最简单的1+2

1的二进制 ····0001

2的二进制 ····0010

3的二进制 ····0011

那a+b不就等于a|b吗?那么,再来验证下1+3

1的二进制 ····0001

3的二进制 ····0011

4的二进制 ····0100

发现之前的猜想错误了,然后再经过一些其他简单的验算,我们会轻而易举的发现一个规律,如果没有进位,那么a+b = a|b 如果有进位就不成立。

所以接下来要处理进位的问题,我们在用1+3来研究下进位的问题,如果我们忽略有进位的位置后,再加上应该进位的位置,就是我们的值。

                             1的二进制(a) ····0001

                             3的二进制(b) ····0011

                 忽略进位的二进制(c) ····0010(忽略有进位的位),既然忽略了进位,那么接下来肯定要加上进位

                        应该进位的值(d) ····0010

我们的值应该是c+d(但是c和d还是有进位,那么再重复上述操作),即:

                                  c的二进制 ····0010

                                  d的二进制 ····0010

                 忽略进位的二进制(e) ····0000     

                          应该进位的值(f) ····0100

    int aplusb(int a, int b) {    
        if((a&b) == 0)  
            return a|b;  
        return aplusb(a^b,(a&b)<<1);  
    }  //错误代码

以上叙述是Copy的某博客的心得 原文章地址在这里博客地址。

但是,原文章犯了个致命的错误:没有想到a b为负数的情况。

在经历了一翻寻找后找到的所有代码基本上都为抄这篇博客的

代码,这让我非常崩溃。。

对于位运算一无所知的我只能从头分析二进制加减法运算规

则。

总结的公式就是:

      补码的加法规则是:[X + Y]补 = [X]补 + [Y]补
       

      补码的减法规则是:[X - Y]补 = [X]补 + [-Y]补

        
int aplusb(int a, int b) {
        int c=0,d=0;
        int t1=a,t2=b;
        if(a<0)a=~(-a)+1;
        if(b<0)b=~(-b)+1;//cout<t2)||(t2<0&&-t2>t1))return ~(-(a|b)-1);
		      return  a|b;
    }//correct
修改后代码如上。

几个注意的点:
           
           1 . 正数的补码还为自己本身。 负数的补码为 ,负数的相反数(绝对值)的反码加1,已知负数为a,则a的补码为~(-a)+1。

     2 .[X + Y]补 = [X]补 + [Y]补。 在这个公式里,x+y

为未知数。所以算完等号右边后应执行反补码的操作。也就是

等号右边-1再求反码。

    3.由于要求等号右边也就是 a|b的补码  必须知道a|b的

正负。所以设定了t1 t2用来判断a|b的正负性。

    4.与本题无关 负数补码的补码就是负数补码的相反数,

而不是单纯的用定义求负数的补码的补码。。比较绕

    


你可能感兴趣的:(LintCode第一题:A + B 问题 (位运算)c++实现)