题干:
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
思路:
首先可以明确,这种算数运算大部分都可以被位运算去代替。因为在计算机中是只有二进制数的,所有的加减乘除本身也是对二进制数的操作。具体我们来总结一下这道题的思路:
不用加减乘除做加法
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号
1、位运算
1.解题思路
使用位运算实现加法
1、一位加法
普通加法
异或
1 + 1 = 0
1 ^ 1 = 0(错误)
1 + 0 = 1
1 ^ 0 = 1(正确)
0 + 1 = 1
0 ^ 1 = 1(正确)
0 + 0 = 0
0 ^ 0 = 0(正确)
问题:没有采取进位操作导致运算错误
难点:如何解决进位问题?
与运算
1 & 1 = 1(进位)
1 & 0 = 0(不进位)
0 & 1 = 0(不进位)
0 & 0 = 0(不进位)
在位运算中,我们用“<<”表示向左移动一位,也就是“进位”。那么我们就可以得到如下的表达式:
- ( x & y ) << 1
拥有了两个基本表达式:
- 执行加法 x ^ y
- 进位操作 ( x & y ) << 1
进位为0时,结束操作
2、二位加法
例子:
- *正确的加法计算:11+01 = 100 *
- 使用位运算实现二位加法:
- 按位加法: res1 = 11 ^ 01 = 10
- 与运算进位: res2 = (11 & 01) << 1 = ( 01 ) << 1 = 010
- res1 ^ res2 = 10 ^ 010 = 00
- (10 & 10) << 1 = 100
- 000 ^ 100 = 100
- (000 & 100) <<1 = 000(进位为0)
所以最终的答案是100.
3、更高位的加法
继续推理可以得出三位数的加法只需重复的计算三次得到第一个表达式的值就是计算出来的结果
三位加法:
- 101 ^ 111 = 0010 (没有处理进位的加法)
(101 & 111) << 1 = 101 << 1 = 1010 (此处得到哪一位需要加上进位,为1的地方表示有进位需要加上) - 0010 ^ 1010 = 1000 (没有处理进位的加法 + 进位 = 没有处理进位的加法)
(0010 & 1010) << 1 = 0010 << 1 = 00100 (查看是否有新的进位需要处理) - 1000 ^ 00100 (没有处理进位的加法 + 进位 = 没有处理进位的加法)
(1000 & 00100) << 1 = 00000 << 1 = 000000 (进位为0,所以没有要处理的进位了)
更高位加法:依上边类推
确定了最终的思路之后,给出代码如下:
public class Solution {
public int Add(int num1,int num2) {
int result=0;
int jinwei=0;
do{
result=num1^num2;
jinwei=(num1&num2)<<1;
num1=result;
num2=jinwei;
}while(jinwei!=0);
return result;
}
}
值得注意的是,位运算比普通的加减乘除要快的多。