题目描述
给你两个整数 a 和 b ,不使用 运算符 + 和 - ,计算并返回两整数之和。
示例 1:
输入:a = 1, b = 2
输出:3
示例 2:
输入:a = 2, b = 3
输出:5
提示:
-1000 <= a, b <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-two-integers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
由于题目中禁止使用 + 或者 -,第一直觉是位运算,使用二进制的运算来模拟加法。
这里需要了解一下二进制位的操作及原码、反码、补码的表示。参考
那这里有几个问题:
- 如何使两个数加起来
01 + 00 = 01
01 + 01 = 10
看样子需要处理进位。
a, b相加时与进位之间的关系
1 + 1 = 0 ; 当两个都为1且不进位的时候,保持位为0 res &= ~i; 同时进位。
; 当两个都为1且进位的时候,保持位1 (res |= i) 同时进位
1 + 0 = 1 ; 当两个数字其中一个不为0时。又有进位时,保持位为0,同时进位
; 当两个数字其中一个不为0时。没有进位时,此位置1,同时消进位
0 + 0 = 0 ; 当两个数都为0 进位时,保持位为1,取消进位
; 当两个数都为0 没有进位时,保持位0
-
如何处理负数
由于负数是补码的形式进行表示。所以需要处理最高位的符号表示。
由于题目中说 x belong [-1000,1000] 那16bit即可表示。
得到结果之后如果第15位的最高位为1即为负数,把res的高16个bit都置1
如果第15位为0即为正数,把res的高16个bit置为0 -
如何进行循环
每次 i从1开始向左移1
依次处理每一个二进制位与进位。
直到 i < (1 << 16) 的条件不能达成。
为什么使用把数字限定在2bytes内?
- 可以减少循环的次数
- 可以比较好处理循环的终点。
代码
class Solution {
public:
int getSum(int a, int b) {
int res = a;
bool carry = false;
for (int i = 1; i < (1 << 16); i <<= 1) {
int res_this_bit = res & i;
int b_this_bit = b & i;
if (res_this_bit != b_this_bit) {
// res,b = (1,0)
if (carry) {
// set res_this_bit to zero
res &= ~i;
continue;
} else {
res |= i;
continue;
}
} else {
if (res_this_bit != 0) {
// all 1
if (!carry) {
carry = true;
res &= ~i;
}
} else {
if (carry) {
res |= i;
carry = false;
}
}
}
}
if ((res & (1 << 15)) != 0) {
return res | 0xFFFF0000;
} else {
return res & 0x0000FFFF;
}
}
};