位運算加法
擴充套件減乘除
給出兩個整數a
和b
,求它們的和
如果a=1
並且b=2
,返回3
.
你可以直接使用return a+b
,但是不使用+
運算子
二進位制00000110
(6),00001011
(11) 按位與運算:
00000110
& 00001011
00000010
總結:同為1
則為1
,否則為0
按位或運算:
00000110
| 00001011
00001111
總結:只要有乙個為1
則為1
,否則為0
按位異或運算:
00000110
^ 00001011
00001101
總結:不相同則為1
,否則為0
按位取反運算:
00000110
~ 11111001
總結:0
為1
,1
為0
左邊消失,右邊補0
右邊消失,左邊補符號位
十進位制中:
13 + 9
操作步驟:
不考慮進製,sum = 13 + 9 = 12
;
只考慮進製,carry= 13 + 9 = 10
;
如果carry != 0
,使用sum
和carry
重複1,2步,直至carry = 0
為止,則結果為sum = 22
;
步驟:
1. sum = 13 + 9 = 12;
2. carry = 13 + 9 = 10;
3. carry != 0;
4. sum = 12 + 10 = 22;
5. carry = 12 + 10 = 0;
6. carry = 0, sum = 22;
二進位制中:
13: 00001101 9: 00001001
1. sum = 00001101 + 00001001 = 00000100;
2. carry = 00001101 + 00001001 = 00010010;
3. carry != 0;
4. sum = 00000100 + 00010010 = 00010110;
5. carry = 00000100 + 00010010 = 00000000;
6. carry = 0, sum = 00010110 = 22;
第一步操作就是按位異或^
操作;
第二步操作是按位與&
操作,再左移<<
1
位.
所以,操作就可以使用遞迴或者迭代方式實現
遞迴**:
int
add(
int num1,
int num2)
int sum = num1 ^ num2;
int carry =
(num1 & num2)
<<1;
return
add(sum, carry)
;}
迭代**:
int
add(
int num1,
int num2)
return sum;
}
13 - 9
可以轉換為13 + (-9)
,然後使用前面的加法方法實現減法
在計算機中,負數是以補碼形式存在的:
-9 原碼: 00001001
反碼: 11110110
補碼: 11110110 + 1 = 11110111
所以-9
在計算機中的表現形式是:11110111
.
~00001001 + 1
就可以得到-9
的表現形式.
總結:取反加一
所以:
int
subtract
(int num1,
int num2)
13 * 9
轉換為加法就是9
個13
相加,符號最後判斷,同號為正,異號為負.
所以:
int
multiply
(int a,
int b)
//判斷正負號, 按位異或,最高位為1則為負數,最高位為0則為正數if(
(a ^ b)
<0)
return sum;
}
上面的方法,如果乘數很大,即9
很大時,需要疊加的次數也就很多,運算起來就會很大,效率不高
可以參考十進位制的乘法:
1 3
* 1 4
5 21 3
1 8 2
二進位制:
1 1 0 1
* 1 1 1 0
0 0 0 0
1 1 0 1
1 1 0 1
1 1 0 1
1 0 1 1 0 1 1 0 (182)
相當於b從低位開始取值,如果為1,則加入sum中,為0,則不需要相加
取b的下一位, 即右移一位,取最低位, a右移一位,相當於在十進位制中乘以10,重複上面.
直到最後b右移為0時,結束,判斷符號
所以優化結果為:
int
multiply
(int a,
int b)
absa = absa <<1;
//a 左移一位, 在十進位制中就是乘於10, 進一位,二進位制中同理
absb = absb >>1;
//b 右移一位, 在十進位制中就是除以10, 退一位, 二進位制中同理
}//判斷符號if(
(a ^ b)
<0)
return sum;
}
除法轉換為減法, 被除數減除數,直到被除數小於除數字置,減的次數就是商,此時被除數就是餘數.符號確認跟乘法一樣,餘數的符號和被除數一樣.
int
divide
(int a,
int b)
//判斷符號if(
(a ^ b)
<0)
//判斷餘數符號
rema = a >
0? absa :
add(
~absa,1)
;return count;
}
跟乘法類似a
很大b
很小 減的次數就很大,所以可以增加步數去減
在計算機中,所有數都可以使用 [20,21,22,…,231] 表示,所以可以從31開始,如果可以減31倍,就把31倍的次數,依次類推
int
divide
(int a,
int b)}if
((a ^ b)
<0)
rema = a >
0? absa :
add(
~absa,1)
;}
結束 a b擴充套件 C
oj的第一道題是經典的a b問題,輸入兩個數,並輸出這兩個數的和。但是你不能僅僅滿足於此,我們要增加需求,加需求!不僅僅是a b,還要繼續加上或者減去其他的數,比如1 2 3 2,輸出4。input 有多組測試資料,每組測試資料報含一行不含有空格的字串,字串長度不超過1000,字串僅包含數字 加號和...
A B 尾數不等a b問題
problem description 讀入兩個小於 10000 的正整數a和 b,計算 a b。需要注意的是 如果a和 b的末尾 k 不超過 8 位數字相同,請直接輸出 1。input 測試輸入包含若干測試用例,每個測試用例佔一行,格式為 a b k 相鄰兩數字有乙個空格間隔。當a和 b同時為 0...
A B 字串a b問題
problem description 讀入兩個小於100的正整數a和b,計算a b.需要注意的是 a和b的每一位數字由對應的英文單詞給出.input 測試輸入包含若干測試用例,每個測試用例佔一行,格式為 a b 相鄰兩字串有乙個空格間隔.當a和b同時為0時輸入結束,相應的結果不要輸出.output...