原题链接: https://leetcode.com/problems/sum-of-two-integers/
1. 题目介绍
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.
Example 1:
Input: a = 1, b = 2
Output: 3
Example 2:
Input: a = -2, b = 3
Output: 1
不使用 + 和 - 来计算两个数的和。
这里我介绍一下利用位操作来完成两个数的加法、减法、求负数的计算。
2. 加法
不能用加减运算符,那就使用位运算来计算和。
我们平时使用加法运算时,是先计算低位,后计算高位。低位相加后会产生进位,高位相加时,需要把低位的进位加进来一起运算。
比如,7+10 = 17,利用二进制计算就是0111+1010=10001
现在我们能不能把两部分分开呢?
不考虑进位的加:
0111+1010 = 1101
只考虑进位,把进位的数位置1:
0111+1010 = 0010
现在,把进位的部分左移一位,然后加上不进位的加法,就可以得到和了。
0010左移一位变成0100,0100+1101 = 10001 = 17(十进制)
不考虑进位的那部分,0+0=0,0+1=1,1+0=1,1+1=0,这就是异或 ^ 的运算规则;
只考虑进位的那部分,0+0=0,0+1=0,1+0=0,1+1=1,这就是与 & 的运算规则。
于是我们可以得出,替代a+b 的方法就是,首先计算 a^b,然后 a&b 左移1位,最后再把两者加起来,可以用递归或者循环来实现。结束递归或者循环的条件是进位为零。
递归实现
class Solution {
public int getSum(int a, int b) {
if(b==0) return a;
int x = a ^ b;
int y = (a & b)<<1 ;
return getSum(x , y);
}
}
循环实现
class Solution {
public int getSum(int a, int b) {
while(b != 0) {
int Carry = a & b;
a = a ^ b;
b = Carry<<1;
}
return a;
}
}
3. 计算差
在计算机中,计算 a-b 可以转化为 a +(-b),而-b的就是b的反码+1,也即 ~b+1。
所以 a - b = a +( ~b+1 )
public int getSubtract(int a, int b) {
b = ~b+1;
while(b != 0) {
int Carry = a & b;
a = a ^ b;
b = Carry<<1;
}
return a;
}
或者
public int getSubtract(int a, int b) {
while (b != 0) {
int borrow = (~a) & b;
a = a ^ b;
b = borrow << 1;
}
return a;
}
4. 求负数
-b = ~b +1
public int negate(int x) {
return ~x + 1;
}
5. 参考链接
https://leetcode.com/problems/sum-of-two-integers/discuss/84290/Java-simple-easy-understand-solution-with-explanation
https://www.cnblogs.com/grandyang/p/5631814.html