A+B问题扩展

A+B  

  要求为给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。在这里我进行了扩展,增加了乘法功能,加法功能是通过检测的,至于乘法功能,我自己测了几组数据是没问题的,至于存不存在漏洞,我也不好说,仅供参考吧。

package com.zhao.project;

public class Project_1 {

    public static void main(String[] args) {
        Project_1 project = new Project_1();
        int sum = project.aplusb(6, -1);
        System.out.println("sum: " + sum);
        sum=project.chengfa(-1, 3);
        System.out.println("result: "+sum);
    }

    /*
     * param a: The first integer param b: The second integer return: The sum of
     * a and b
     */
    public int aplusb(int a, int b) {
        /*
         * 按位与 & 二者都为1,结果才是1 否则都为0。 按位或| 二者都为0,结果才是0 否则都为1。 按位异或^ 相同为0 相反为1
         */
        int c = a & b;
        if (c != 0) {
            a = a ^ c;
            b = b ^ c;
            c = c << 1;
            int result = aplusb(a | b, c);
            return result;
        } else {
            return a | b;
        }

    }
    public int chengfa(int a,int b){
        int c=0;
        int sum=0;
        for(int i=0;i<31;i++){
            c=b&1;
            if(c!=0){
                sum=aplusb(a<<i, sum);
            }
            b=b>>1;
        }
        return sum;
    }

}

加法分析:

  位运算总共只有5种运算:与、或、异或、左移、右移,  按位与 & 二者都为1,结果才是1 否则都为0。 按位或| 二者都为0,结果才是0 否则都为1。 按位异或^ 相同为0 相反为1。左移运算符m<<n表示吧m左移n位。左移n位的时候,最左边的n位将被丢弃,同时在最右边补上n个0。右移运算符m>>n表示把m右移n位。右移n位的时候,最右边的n位将被丢弃。

  我在做加法的时候首先用了6+1,6=0110,1=0001,显然二者按位或,为0111,结果是正确的。可是如果是6+3,即0110+0011,一存在进位问题就失败了。要想做好这个加法 最重要的就是解决这个进位问题。  0 1 1 0  0 0 1 1c=a&b=0010 我们需要把结果第三位设置为0,然后在第二位上加1.显然我们是在a|b=0111的基础上操作的。a^c=得到a中除了需要进位那一位其余的数,b^c得到了b中其余的数。此时的a和b显然是没有同时为1的位的。这样就很方便a|b来得到结果,目前的结果是0101,如愿以偿的把第三位设置为0了。还需要完成进位 也就是 0101+0100,我们有0010,是通过最开始的a&b得到的,能显示的看出来是第三位,要想知道在哪一位上+1 ,c=c<<1;得到的c是0100,接下来我们的问题就是0101+0100了,显然第二位上又是两1,问题重复了,好吧,递归来了。我们接着处理这两个数,当成a和b ,只有a和b完成没有相同位为1的时候,我们用a|b得到结果才可以。 

乘法分析:
  还是0110 和 0011
   0 1 1 0
* 0 0 1 1
  0 1 1 0
0 1 1 0
1 0 0 1 0
在纸上进行过这个运算,才觉得和加法好像啊。思路更清晰了,就是好几个数加在一起。a=0110 b=0011,我们只需要得到b的每一位,不是0 就是1 ,有一个1就加一个0110,是0就不加了。但是 需要注意的是,0110后面会补0 补多少0得看情况。
既然是累加,肯定有sum=0,b除了符号位,应该有31位,好,循环31次,依次得到b的每一位。c=b&1;这样就把b前面清零了,只有最后一位。如果为1 a左移之后加上sum。为什么左移,可以看看乘法的式子,是有一个往左走的过程,所以当i=0时,也就是第一次,是不左移的,也可以说左移为0.以后每次依次左移相应的位数,幸好我们有i这个变量,可以轻松的实现这一过程。不管c是0还是1 b都需要右移,而且每次移动一位,这样才能确保,我们通过读b的最后一位可以把b这个32位的正数都读完,当然 读31位就够了。加法的过程思路和上面一样。 
原文地址:https://www.cnblogs.com/zhao307/p/5399425.html