算法小記 · 不用四則運(yùn)算做加法

寫一個(gè)函數(shù),求兩個(gè)整數(shù)之和太抓,要求在函數(shù)體內(nèi)不得使用 +空闲、-、*走敌、/ 四則運(yùn)算符號(hào)碴倾。

輸入:

輸入可能包含多個(gè)測(cè)試樣例。
對(duì)于每個(gè)測(cè)試案例,輸入為兩個(gè)整數(shù) x 和 y (1 <= m, n <= 1000000)影斑。

輸出:

對(duì)應(yīng)每個(gè)測(cè)試案例给赞,輸出 x + y 的值。

樣例輸入:

1 2
11 18

樣例輸出:

3
29

首先矫户,思考的是片迅,不能用四則運(yùn)算符,只能從別的角度來考慮皆辽。
那么柑蛇,用過C語言的,自然就得考慮到C語言的優(yōu)勢(shì)之一 按位運(yùn)算驱闷。

吾來打個(gè)樣:

#include <stdio.h>
// 主要的方法是用與來求進(jìn)位耻台,用異或來求不進(jìn)位的加法
unsigned int Add(unsigned int a, unsigned int b) 
{
    unsigned int sum, carry;
    
    do {
        // 按位異或運(yùn)算
        sum = a ^ b;
        // 按位與運(yùn)算后,再進(jìn)行按位左移運(yùn)算
        // << 1 相當(dāng)于 *2
        carry = (a & b) << 1;
        
        a = sum;
        b = carry;
    } while (b != 0); // 對(duì)carry的值做判斷空另,不滿足條件的盆耽,則為正確的sum值
    
    return a;
}

int main(int argc, const char * argv[]) {
    unsigned int x, y;
    while (scanf("%u%u", &x, &y) != EOF) {
        printf("%u\n", Add(x, y));
    }
    return 0;
}

關(guān)于按位運(yùn)算的些許補(bǔ)充(不了解的或遺忘了的,可以看看):

C 語言 和其它高級(jí)語言不同的是扼菠,它完全支持 按位運(yùn)算符摄杂。這與 匯編語言位操作 有些相似。
因?yàn)?位運(yùn)算 得到了更多的底層優(yōu)化循榆,因此同樣的功能它的 效率更高析恢。

所謂 位運(yùn)算,就是對(duì)一個(gè) 比特(Bit)位 進(jìn)行操作秧饮。比特(Bit) 是一個(gè)電子元器件映挂,8 個(gè)比特 構(gòu)成 一個(gè)字節(jié)(Byte),它已經(jīng)是 粒度最小可操作單元 了盗尸。

// C語言中提供的六種按位運(yùn)算符
& 位邏輯與
| 位邏輯或
^ 位邏輯異或
~ 位邏輯反
>> 右移
<< 左移
標(biāo)準(zhǔn)的 C 語言其實(shí)并不支持二進(jìn)制數(shù)字柑船,只不過有些編譯器自己進(jìn)行了擴(kuò)展,才支持二進(jìn)制數(shù)字振劳。換句話講就是椎组,并非所有的編譯器都支持二進(jìn)制數(shù)字油狂,只有一部分編譯器支持历恐,并且跟編譯器的版本還有關(guān)系。

C 語言中不能直接使用 二進(jìn)制 數(shù)字专筷,按位運(yùn)算符 兩邊的操作數(shù)可以是十進(jìn)制弱贼、八進(jìn)制、十六進(jìn)制磷蛹,因?yàn)樗鼈冊(cè)趦?nèi)存中最終皆是以 二進(jìn)制 的形式存儲(chǔ)吮旅,按位運(yùn)算符就是對(duì)這些 內(nèi)存中二進(jìn)制位 進(jìn)行運(yùn)算。其他的位運(yùn)算符也是相同的道理。

提醒按位運(yùn)算符 是根據(jù)內(nèi)存中的二進(jìn)制位進(jìn)行運(yùn)算的庇勃,而不是數(shù)據(jù)的二進(jìn)制形式檬嘀;其他位運(yùn)算符也一樣。

按位與運(yùn)算 (&)

    /*
     * 按位與運(yùn)算 (&)
     * 一個(gè)比特(Bit)位只有 0 和 1 兩個(gè)取值责嚷,只有參與 & 運(yùn)算的兩個(gè)位都為 1 時(shí)鸳兽,結(jié)果才為 1,否則為 0罕拂。
     * 例如:1 & 1為 1揍异,0 & 0為 0,1 & 0也為 0爆班,這和邏輯運(yùn)算符 && 非常類似衷掷。
     * 
     *   0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0010  //表示十進(jìn)制的 2 (在內(nèi)存中的的存儲(chǔ))
     * & 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001  //表示十進(jìn)制的 1 (在內(nèi)存中的的存儲(chǔ))
     * ---------------------------------------------------
     *   0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0000  //表示十進(jìn)制的 0 (在內(nèi)存中的的存儲(chǔ))
     *
     */
    int m = 2;
    int n = 1;
    printf("%d \n", (m & n));  //輸出為 0

按位或運(yùn)算 (|)

    /*
     * 按位或運(yùn)算 (|)
     * 一個(gè)比特(Bit)位只有 0 和 1 兩個(gè)取值,只要參與 | 運(yùn)算的兩個(gè)二進(jìn)制位有一個(gè)為 1 時(shí)柿菩,結(jié)果就為 1戚嗅,兩個(gè)都為 0 時(shí)結(jié)果才為 0。
     * 例如:1 | 1為 1枢舶,0 | 0為 0渡处,1 | 0為 1,這和邏輯運(yùn)算中的||非常類似祟辟。
     *
     *   0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0010  //表示十進(jìn)制的 2 (在內(nèi)存中的的存儲(chǔ))
     * | 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001  //表示十進(jìn)制的 1 (在內(nèi)存中的的存儲(chǔ))
     * ---------------------------------------------------
     *   0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0011  //表示十進(jìn)制的 3 (在內(nèi)存中的的存儲(chǔ))
     *
     */
    int m = 2;
    int n = 1;
    printf("%d\n", (m | n));  //輸出為 3

按位異或運(yùn)算 (^)

    /*
     * 按位異或運(yùn)算(^)
     * 一個(gè)比特(Bit)位只有 0 和 1 兩個(gè)取值医瘫,只要當(dāng)參與 ^ 運(yùn)算兩個(gè)二進(jìn)制位不同時(shí),結(jié)果就為 1旧困,相同時(shí)結(jié)果則為 0醇份。
     * 例如:0 ^ 1為 1,0 ^ 0為 0吼具,1 ^ 1為 0僚纷。
     * 
     *   0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0010  //表示十進(jìn)制的 2 (在內(nèi)存中的的存儲(chǔ))
     * ^ 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001  //表示十進(jìn)制的 1 (在內(nèi)存中的的存儲(chǔ))
     * ---------------------------------------------------
     *   0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0011  //表示十進(jìn)制的 3 (在內(nèi)存中的的存儲(chǔ))
     *    
     */
    int m = 2;
    int n = 1;
    printf("%d\n", (m ^ n));  //輸出為 3

取反運(yùn)算 (~)

    /*
     * 取反運(yùn)算(~)
     * 一個(gè)比特(Bit)位只有 0 和 1 兩個(gè)取值,取反運(yùn)算符~為單目運(yùn)算符拗盒,右結(jié)合性怖竭,作用是對(duì)參與運(yùn)算的二進(jìn)制位取反。
     * 例如:~1為 0陡蝇,~0為 1痊臭,這和邏輯運(yùn)算中的!非常類似。
     * ~ 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001  //表示十進(jìn)制的 1 (在內(nèi)存中的的存儲(chǔ))
     * ---------------------------------------------------
     *   1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 1110  //表示十進(jìn)制的 -2 (在內(nèi)存中的的存儲(chǔ))
     * 在計(jì)算機(jī)中登夫,負(fù)數(shù)以原碼的補(bǔ)碼形式表達(dá)广匙。
     * 正數(shù)的補(bǔ)碼與原碼相同,負(fù)數(shù)的補(bǔ)碼為對(duì)該數(shù)的原碼(除符號(hào)位外)逐位取反恼策,然后在最后一位加 1鸦致。
     * 二進(jìn)制中,如果有符號(hào), 最高位表示符號(hào), 0 為正, 1 為負(fù),
     * -2 的二進(jìn)制原碼是:1000 0000 -- 0000 0000 -- 0000 0000 - 0000 0010
     * -2 的二進(jìn)制補(bǔ)碼是:1111 1111 -- 1111 1111 -- 1111 1111 - 1111 1101
     * -2 的o二進(jìn)制補(bǔ)碼加1 是:1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 1110
     */
    int n = 1;
    printf("%d\n", (~ n));  //輸出為 -2

左移運(yùn)算 (<<)

    /*
     * 左移運(yùn)算 (<<)
     * 一個(gè)比特(Bit)位只有 0 和 1 兩個(gè)取值分唾,左移運(yùn)算符<< 就是把操作數(shù)的各個(gè)二進(jìn)制位全部左移若干位抗碰,高位丟棄,低位補(bǔ) 0绽乔。
     *
     * << 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001  //表示十進(jìn)制的 1 (在內(nèi)存中的的存儲(chǔ))
     * ---------------------------------------------------
     *    0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1000  //表示十進(jìn)制的 8 (在內(nèi)存中的的存儲(chǔ))
     *
     */
    int n = 1;
    printf("%d\n", (n << 3));  //輸出為 8

右移運(yùn)算(>>)

    /*
     * 右移運(yùn)算 (>>)
     * 一個(gè)比特(Bit)位只有 0 和 1 兩個(gè)取值改含,右移運(yùn)算符>> 就是把操作數(shù)的各個(gè)二進(jìn)制位全部右移若干位,低位丟棄迄汛,高位補(bǔ) 0 或 1捍壤。
     * 如果數(shù)據(jù)的最高位是 0,那么就補(bǔ) 0鞍爱;如果最高位是 1鹃觉,那么就補(bǔ) 1。
     *
     * >> 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001  //表示十進(jìn)制的 1 (在內(nèi)存中的的存儲(chǔ))
     * ---------------------------------------------------
     *    0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0000  //表示十進(jìn)制的 0 (在內(nèi)存中的的存儲(chǔ))
     *
     */
    int n = 1;
    printf("%d\n", (n >> 3));  //輸出為 0
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末睹逃,一起剝皮案震驚了整個(gè)濱河市盗扇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沉填,老刑警劉巖疗隶,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異翼闹,居然都是意外死亡斑鼻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門猎荠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坚弱,“玉大人,你說我怎么就攤上這事关摇』囊叮” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵输虱,是天一觀的道長(zhǎng)些楣。 經(jīng)常有香客問我,道長(zhǎng)宪睹,這世上最難降的妖魔是什么愁茁? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮横堡,結(jié)果婚禮上埋市,老公的妹妹穿的比我還像新娘冠桃。我一直安慰自己命贴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胸蛛,像睡著了一般污茵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上葬项,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天泞当,我揣著相機(jī)與錄音,去河邊找鬼民珍。 笑死襟士,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嚷量。 我是一名探鬼主播陋桂,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蝶溶!你這毒婦竟也來了嗜历?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤抖所,失蹤者是張志新(化名)和其女友劉穎梨州,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體田轧,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡暴匠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了傻粘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巷查。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖抹腿,靈堂內(nèi)的尸體忽然破棺而出岛请,到底是詐尸還是另有隱情,我是刑警寧澤警绩,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布崇败,位于F島的核電站,受9級(jí)特大地震影響肩祥,放射性物質(zhì)發(fā)生泄漏后室。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一混狠、第九天 我趴在偏房一處隱蔽的房頂上張望岸霹。 院中可真熱鬧,春花似錦将饺、人聲如沸贡避。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刮吧。三九已至湖饱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杀捻,已是汗流浹背井厌。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留致讥,地道東北人仅仆。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像垢袱,于是被迫代替她去往敵國(guó)和親蝇恶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容