題目來自 力扣(LeetCode)
題目描述
不使用運算符+
和-
,計算兩整數 a
、b
之和。
示例
示例 1:
輸入: a = 1, b = 2
輸出: 3
示例 2:
輸入: a = -2, b = 3
輸出: 1
分析
第一眼看到題目就心想,這不是很簡單麼,異或、位運算,不就行了?
看了第二眼,爲什麼異或就能解決這個問題呢!?
異或 ^ 1
相異爲一
A | B | A^B |
---|---|---|
1 | 0 | 1 |
1 | 1 | 0 |
0 | 1 | 1 |
0 | 0 | 0 |
通過觀察異或運算的真值表,與加法的真值表特別地像。需要注意的是異或只看本位,加法可能需要進位。從而用到與運算&。
與 &
全一爲一
A | B | A&B |
---|---|---|
1 | 0 | 0 |
1 | 1 | 1 |
0 | 1 | 0 |
0 | 0 | 0 |
與運算可以很好地解決加法進位的問題,加法進位和與運算結果對應:1+0、0+1、0+0的進位都是0,1+1的進位爲1。
通過異或得到了本位和,通過與運算得到了進位值,最後,只需要將進位值給高一位即可。
左移 <<
挺好理解的,將進位值左移到高位參與加法運算。
不管是無符號數,還是有符號數,不管是正數,還是負數,左移都是所有位參與,高位捨棄,低位補零。
-
如果b爲0,結果爲a
-
否則,將a^b的結果(每一位的本位和)與a&b後左移一位的結果(每一位的進位)相加(遞歸\迭代)。
注意
LeetCode中國版的C++好像不支持負值左移,會報錯:
runtime error: left shift of negative value -2147483648 (solution.cpp)
需要強轉爲無符號數(unsigned int)。
代碼
C++:
//C++
class Solution {
public:
int getSum(int a, int b) {
return b==0? a:getSum(a^b, (unsigned int)(a&b)<<1);
}
};
補充
牛客網《劍指Offer》上有一道類似的題目(支持負值左移)不用加減乘除做加法。
顧名思義,不一樣(異)的話就或運算,一樣的話就得零。二進制只有0和1,或運算得到1。即,相異爲一。 ↩︎