昨天在leetcode做題的時候做到了371,原題是這樣的:
371. Sum of Two Integers
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.
Example:
Given a = 1 and b = 2, return 3.
因為之前完全沒有在實際練習中使用過位運算,所以剛看到這道題目的時候我的第一反應是
1.用乘除代替加減,但是一想,覺得恐怕不行,因為乘除本質上也是加減法,不可能跳過加減法做運算。
2.然后又想到或許可以轉成二進制再用邏輯運算計算?但是問題是轉成二進制不難,但是轉回來還是得用加減法呀!看來這種方法也不行。
3.於是想到位運算,但是由於對位運算很不熟悉,於是上網搜了一下,得到如下表格:
含義 |
Pascal語言 | C語言 | Java |
---|---|---|---|
按位與 | a and b | a & b | a & b |
按位或 | a or b | a | b | a | b |
按位異或 | a xor b | a ^ b | a ^ b |
按位取反 | not a | ~a | ~a |
左移 | a shl b | a << b | a << b |
帶符號右移 | a shr b | a >> b | a >> b |
無符號右移 | a>>> b |
好吧,其實一看都是一些布爾運算,也不難理解,接下來就是運算問題了。
舉個例子試試看怎么算吧,比如3 + 1,該怎么算呢?由於位運算都是基於二進制的也就是3 + 1 = (011) + (001),如果列豎式計算的話就是
0 1 1
+ 0 0 1
-----------
0 1 0
+ 0 1 0
-----------
1 0 0
看懂了嗎?其實就是模擬進位:
1.首先最低位相加是要進一的
2.然后在做第二位的運算
3.以此類推,一直到沒有進位為止。
那么必須弄清楚什么時候需要進位,很明顯,當同一位上的數字都是1的時候需要進位,進位以后下一位變成1,也就是3 & 1中等於1的地方是需要進位的,然后左一一位,使下一位變成1, 然后下一位需要加的數字就是 3 ^ 1。
C++代碼實現如下:
int getSum(int a, int b) { while(a != 0) { int tmp = (a & b) << 1; b = a ^ b; a = tmp; } return b; }