题目描述

给你两个整数 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

由于题目中禁止使用 + 或者 -,第一直觉是位运算,使用二进制的运算来模拟加法。
这里需要了解一下二进制位的操作及原码、反码、补码的表示。参考

那这里有几个问题:

  1. 如何使两个数加起来
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
  1. 如何处理负数
    由于负数是补码的形式进行表示。所以需要处理最高位的符号表示。
    由于题目中说 x belong [-1000,1000] 那16bit即可表示。
    得到结果之后如果第15位的最高位为1即为负数,把res的高16个bit都置1
    如果第15位为0即为正数,把res的高16个bit置为0

  2. 如何进行循环
    每次 i从1开始向左移1
    依次处理每一个二进制位与进位。
    直到 i < (1 << 16) 的条件不能达成。

为什么使用把数字限定在2bytes内?

  1. 可以减少循环的次数
  2. 可以比较好处理循环的终点。

代码

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;
        }
    }
};