演算法小記·不用四則運算做加法
寫一個函式,求兩個整數之和,要求在函式體內不得使用 +、-、*、/ 四則運算子號。
輸入:
輸入可能包含多個測試樣例。
對於每個測試案例,輸入為兩個整數 x 和 y (1 <= m, n <= 1000000)。
輸出:
對應每個測試案例,輸出 x + y 的值。
樣例輸入:
1 2
11 18
樣例輸出:
3
29
首先,思考的是,不能用四則運算子
,只能從別的角度來考慮。
那麼,用過C語言的,自然就得考慮到C語言的優勢之一 按位運算
。
吾來打個樣:
#include <stdio.h>
// 主要的方法是用與來求進位,用異或來求不進位的加法
unsigned int Add(unsigned int a, unsigned int b)
{
unsigned int sum, carry;
do {
// 按位異或運算
sum = a ^ b;
// 按位與運算後,再進行按位左移運算
// << 1 相當於 *2
carry = (a & b) << 1;
a = sum;
b = carry;
} while (b != 0); // 對carry的值做判斷,不滿足條件的,則為正確的sum值
return a;
}
int main(int argc, const char * argv[]) {
unsigned int x, y;
while (scanf("%u%u", &x, &y) != EOF) {
printf("%u
", Add(x, y));
}
return 0;
}
關於按位運算的些許補充(不瞭解的或遺忘了的,可以看看):
C 語言
和其它高階語言不同的是,它完全支援
按位運算子
。這與組合語言
的位操作
有些相似。
因為位運算
得到了更多的底層優化,因此同樣的功能它的效率更高
。所謂
位運算
,就是對一個位元(Bit)位
進行操作。位元(Bit)
是一個電子元器件,8 個位元
構成一個位元組(Byte)
,它已經是粒度最小
的可操作單元
了。
// C語言中提供的六種按位運算子
& 位邏輯與
| 位邏輯或
^ 位邏輯異或
~ 位邏輯反
>> 右移
<< 左移
標準的 C 語言其實並不支援二進位制數字,只不過有些編譯器自己進行了擴充套件,才支援二進位制數字。換句話講就是,並非所有的編譯器都支援二進位制數字,只有一部分編譯器支援,並且跟編譯器的版本還有關係。
C 語言中不能直接使用 二進位制
數字,按位運算子
兩邊的運算元可以是十進位制、八進位制、十六進位制,因為它們在記憶體中最終皆是以 二進位制
的形式儲存,按位運算子
就是對這些 記憶體中
的 二進位制位
進行運算。其他的位運算子也是相同的道理。
提醒
:按位運算子
是根據記憶體中的二進位制位進行運算的,而不是資料的二進位制形式;其他位運算子也一樣。
按位與運算 (&)
/*
* 按位與運算 (&)
* 一個位元(Bit)位只有 0 和 1 兩個取值,只有參與 & 運算的兩個位都為 1 時,結果才為 1,否則為 0。
* 例如:1 & 1為 1,0 & 0為 0,1 & 0也為 0,這和邏輯運算子 && 非常類似。
*
* 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0010 //表示十進位制的 2 (在記憶體中的的儲存)
* & 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001 //表示十進位制的 1 (在記憶體中的的儲存)
* ---------------------------------------------------
* 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0000 //表示十進位制的 0 (在記憶體中的的儲存)
*
*/
int m = 2;
int n = 1;
printf("%d
", (m & n)); //輸出為 0
按位或運算 (|)
/*
* 按位或運算 (|)
* 一個位元(Bit)位只有 0 和 1 兩個取值,只要參與 | 運算的兩個二進位制位有一個為 1 時,結果就為 1,兩個都為 0 時結果才為 0。
* 例如:1 | 1為 1,0 | 0為 0,1 | 0為 1,這和邏輯運算中的||非常類似。
*
* 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0010 //表示十進位制的 2 (在記憶體中的的儲存)
* | 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001 //表示十進位制的 1 (在記憶體中的的儲存)
* ---------------------------------------------------
* 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0011 //表示十進位制的 3 (在記憶體中的的儲存)
*
*/
int m = 2;
int n = 1;
printf("%d
", (m | n)); //輸出為 3
按位異或運算 (^)
/*
* 按位異或運算(^)
* 一個位元(Bit)位只有 0 和 1 兩個取值,只要當參與 ^ 運算兩個二進位制位不同時,結果就為 1,相同時結果則為 0。
* 例如:0 ^ 1為 1,0 ^ 0為 0,1 ^ 1為 0。
*
* 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0010 //表示十進位制的 2 (在記憶體中的的儲存)
* ^ 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001 //表示十進位制的 1 (在記憶體中的的儲存)
* ---------------------------------------------------
* 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0011 //表示十進位制的 3 (在記憶體中的的儲存)
*
*/
int m = 2;
int n = 1;
printf("%d
", (m ^ n)); //輸出為 3
取反運算 (~)
/*
* 取反運算(~)
* 一個位元(Bit)位只有 0 和 1 兩個取值,取反運算子~為單目運算子,右結合性,作用是對參與運算的二進位制位取反。
* 例如:~1為 0,~0為 1,這和邏輯運算中的!非常類似。
* ~ 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001 //表示十進位制的 1 (在記憶體中的的儲存)
* ---------------------------------------------------
* 1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 1110 //表示十進位制的 -2 (在記憶體中的的儲存)
* 在計算機中,負數以原碼的補碼形式表達。
* 正數的補碼與原碼相同,負數的補碼為對該數的原碼(除符號位外)逐位取反,然後在最後一位加 1。
* 二進位制中,如果有符號, 最高位表示符號, 0 為正, 1 為負,
* -2 的二進位制原碼是:1000 0000 -- 0000 0000 -- 0000 0000 - 0000 0010
* -2 的二進位制補碼是:1111 1111 -- 1111 1111 -- 1111 1111 - 1111 1101
* -2 的o二進位制補碼加1 是:1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 1110
*/
int n = 1;
printf("%d
", (~ n)); //輸出為 -2
左移運算 (<<)
/*
* 左移運算 (<<)
* 一個位元(Bit)位只有 0 和 1 兩個取值,左移運算子<< 就是把運算元的各個二進位制位全部左移若干位,高位丟棄,低位補 0。
*
* << 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001 //表示十進位制的 1 (在記憶體中的的儲存)
* ---------------------------------------------------
* 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1000 //表示十進位制的 8 (在記憶體中的的儲存)
*
*/
int n = 1;
printf("%d
", (n << 3)); //輸出為 8
右移運算(>>)
/*
* 右移運算 (>>)
* 一個位元(Bit)位只有 0 和 1 兩個取值,右移運算子>> 就是把運算元的各個二進位制位全部右移若干位,低位丟棄,高位補 0 或 1。
* 如果資料的最高位是 0,那麼就補 0;如果最高位是 1,那麼就補 1。
*
* >> 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001 //表示十進位制的 1 (在記憶體中的的儲存)
* ---------------------------------------------------
* 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0000 //表示十進位制的 0 (在記憶體中的的儲存)
*
*/
int n = 1;
printf("%d
", (n >> 3)); //輸出為 0
相關文章
- 演算法(3)簡單四則運算演算法
- 四則運算
- 結對程式設計 小學四則運算程式設計
- 79 不用加減乘除做加法
- [記錄] 通用封裝函式——四則運算封裝函式
- Numpy 加法運算,opencv 加法運算,影像的融合OpenCV
- 結對程式設計——小學四則運算練習題小程式程式設計
- 四則運算專案
- 四則運算手冊
- JavaScript + 加法運算子JavaScript
- JavaScript (+) 加法運算子JavaScript
- 結對程式設計--自動生成小學四則運算程式設計
- Java簡單四則運算Java
- OJ1038 四則運算
- 四則運算計算器
- 加法小計算
- 每日一練(34):不用加減乘除做加法
- python四則運算生成器Python
- 結對專案四則運算
- java大整數四則運算Java
- 【劍指offer】65. 不用加減乘除做加法
- JS加法運算全解析JS
- 四則運算+-×÷同時成立的四連環(2)
- 四則運算+-×÷同時成立的四連環(4)
- 四則運算+-×÷同時成立的四連環(3)
- 四則運算+-×÷同時成立的四連環(1)
- 四則運算+-×÷同時成立的四連環(6)
- 使用位運算進行加法運算
- 軟體工作四則運算測試
- 結對程式設計-四則運算程式設計
- [每日一題] 第六題:不用加減乘除做加法每日一題
- LeetCode 劍指 Offer 65. 不用加減乘除做加法LeetCode
- 正則學習小記
- 實現一個自動生成小學四則運算題目的命令列程式命令列
- python資料型別和四則運算Python資料型別
- 結對編碼-四則運算 2252118 2252121
- 課後作業——30道四則運算
- XJSON 是如何實現四則運算的?JSON