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位就够了。加法的过程思路和上面一样。