[剑指offer]不用加减乘除做加法
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
示例:
输入: a = 1, b = 1
输出: 2
提示:
a, b 均可能是负数或 0
结果不会溢出 32 位整数
解题思路
- 无进位的求和, 想象10进制下的模拟情况:如19+1=20,无进位求和就是10,而非20,因为它不管进位情况
- 进位数的和,想象10进制下模拟情况:如9+1=10,得到的进位数为1,而不是10,所以要用<<1向左再移动一位,就变为10了
设两数字的二进制形式 a, b ,其求和 s = a + b,a(i) 代表 a 的二进制第 i 位,则分为以下四种情况:
a[i] | b[i] | 进位和c(i) | 非进位和n(i) |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 |
1 | 0 | 1 | 0 |
1 | 1 | 1 | 0 |
可以发现 进位和 和 与运算 逻辑相同,非进位和 和 异或运算 逻辑相同,因此无进位和 n 和进位和 c 的计算公式为:
{
n
=
a
⊕
b
a
>
0
非
进
位
和
:
异
或
运
算
c
=
a
&
b
<
<
1
a
≤
0
进
位
:
与
运
算
+
左
移
一
位
\begin{cases} n=a\oplus b \qquad & a \gt 0 非进位和:异或运算 \\ c=a\&b<<1 \qquad & a \le 0 进位:与运算+左移一位 \end{cases}
{n=a⊕bc=a&b<<1a>0非进位和:异或运算a≤0进位:与运算+左移一位
即可转化为:
(
和
s
)
=
(
非
进
位
和
n
)
+
(
进
位
和
c
)
(和s)=(非进位和n)+(进位和c)
(和s)=(非进位和n)+(进位和c)
实现代码
class Solution {
public:
int add(int a, int b) {
while(b!=0){
int c=(unsigned int)(a&b)<<1;//进位,C++中负数不支持左移位
a^=b;//非进位
b=c;
}
return a;
}
};