目录
核心公式:A+B= A^B + (A&B)<<1;(当(A&B)<<1 等于 0时, A+B = A^B )
由于实现加法器我们只能使用位运算符,所以我们要想办法把公式化为 A+B = A^B,也就是不再产生进位:((A&B)<<1),因此我们把A + B = (A^B) + ((A&B)<<1)中的 (A^B) 和 ((A&B)<<1)看成新的A和B,不断递归调用 A + B = (A^B) + ((A&B)<<1),直到((A&B)<<1) == 0。
1.算法思想
位运算中两数进行异或运算可以提供两数加和后二进制非进位信息,位运算中的两数进行与运算的结果可以提供两数加和后的二进制进位信息。
总结一下就是:
(1) 当前位的和值等于 A(i)^B(i)
(2) 进位等于 A(i)&B(i),进位需要加在计算位的前一位,所以左移1位,即A(i)&B(i)<<1
所以得到规律: A+B=A^B+(A&B)<<1;因此我们将两数与运算的结果进行循环左移一位(获得进位),并在下一轮循环中继续将移位后的进位结果和非进位结果求和,重复此过程,直到不再进位为止。
具体做法:
- step 1:两数进行与运算可以产生进位的信息
- step 2:运算后执行左移1位就是每轮需要进位的方案
- step 3:两数进行异或运算可以产生非进位的加和结果
- step 4:将移位后的进位结果与非进位结果继续重复 step 1 - step 3 的步骤,直到不再产生进位为止
2.代码实现
迭代版本:
迭代版本: class Solution { public: int Add(int num1, int num2) { while(num2) { int sum = num1 ^ num2; int tmp = (num1 & num2) << 1; num1 = sum; num2 = tmp; } return num1; } };
递归版本:
递归版本: class Solution { public: int Add(int num1, int num2) { if((num1 & num2) << 1) return Add(num1 ^ num2, (num1 & num2) << 1); return num1 ^ num2; } };
其他方法:自增
//其他方法: class Solution { public: int Add(int num1, int num2) { if(num1 >= 0) { while(num1) { num1--; num2++; } } else { while(num1) { num1++; num2--; } } return num2; } };