如何用一個加號計算三個數的和

來源:互聯網
上載者:User

計算三個數字加和的方法是 ( a ^ b ^ c ) + ( ( ( a & b ) | ( b & c ) | ( a & c ) ) << 1 ) ...

 但如果你要問這個公式是哪裡來的 ... 你就要先弄明白什麼是 加法 ...

還沒學會如何邁開腳步又怎麼能跑起來 ... 三個數字之前 ... 我們先要從兩個數字相加開始 ...

首先你要知道電腦裡面的數字都是以二進位儲存的 ... 你看到的數字 ... 在電腦看來都是 0 和 1 ...

我們隨便挑兩個數字比如 123 和 321 ... 轉化成二進位之後用用豎式把它們加在一起 ...

    '    "'    001111011  = 123 + 101000001  = 321-------------   110111100  = 444

相同位置對齊 ... 從個位元加起 ... 相加的結果滿二進一 ... 這個不用我多說了吧 ..?

你可能會注意到 ... 在豎式的上方我有加 ' 和 " 符號
... 這表示進位 ...

這兩個符號的區別是 ' 表示由原來的數字產生的進位 ... " 表示由 ' 產生的進位
...

不過事實上 ... 進位這個事情本身也是二進位 ... 0 和 1 嘛 ... 所以不妨就用二進位來表示 ...

把所有由原來的數字產生的進位也就是 ' 寫成 1 ... 其他填 0 ... 結果像這樣 ...

   001111011  ( a   101000001  ( b   010000010  ( c

我們得到了三個數字 ... a 和 b 是原來的數字 ... c 是進位 ...

回想我們剛剛豎式計算的過程 ... 是不是每次都是先計算一位的值 ... 然後再看有沒有進位要加 ..?

我們現在用程式類比這個過程 ... 不考慮進位的時候先把 a 和 b 相加 ...

在只有一位的時候 ... 0 ^ 0 = 0 1
^ 0 = 1
 0 ^ 1 = 1 1
^ 1 = 0
 ... 只有這四種情況 ...

不知道你有沒有發現 ... 在這種情況下 ... 我沒有使用 + 而是用 ^ 得到了同樣正確的結果
...

^ 就是位元運算操作符裡面的 按位異或 ...
簡單的解釋就是兩個數字相同就返回 0 不同就返回 1 ...

關於位元運算這裡就不再贅述了 ...

總之 ... a 和 b 不進位相加之後 ... 我們的式子變成了這樣 ...

         '   010000010  ( c + 100111010  ( d-------------   110111100  = 444

其中 d = a ^ b ... 我們就這樣成功把 a 和 b 相加的問題轉化成了 c 和 d 相加的問題 ...

但是同時又出現了新的問題 ... 怎麼得到 c ..?

回想一下 ... c 是怎麼來的 ..? 是由進位轉化來的 ... 進位又是怎麼來的 ..? 滿二進一 ...

也就是當 a 和 b 的某一位同時為 1 的時候 ... c 的相應位置的左邊一位為 1 ...

換言之 ... 當 a 和 b 的左起第 n + 1 位同時為 1 的時候則 c 的左起第 n 位為 1 ...

用式子來描述就是 c = ( a & b ) << 1 ...

& 是位元運算操作符裡面的 按位與 ... << 是位元運算操作符裡面的 左移 ...

如果你認真看了我剛剛說的那個在另外問題裡的回答的話 ... 應該不會對這兩個操作符有疑問 ...

到現在為止 ... 我們又把 c 和 d 轉化回了與 a 和 b 相關的式子 ...

總結一下 ... 不考慮進位的計算結果是 a ^ b ... 進位的部分是 (
a & b ) << 1
 ...

所以我們可以得到結論 ... a + b = ( a ^ b ) + ( ( a & b ) << 1 ) ...

繞了一大圈 ... 我們學會了怎麼把兩個數相加改為另外兩個數相加 ...

這個看似沒用的式子 ... 恰恰是解決這道題的關鍵 ...

如果你願意 ... 可以一直這麼寫下去 ... 比如把這個式子繼續拆分變成下面的樣子 ...

(a ^ b) ^ ( ( a & b ) << 1 ) + ( ( a ^ b ) & ( ( a & b ) << 1 ) )

然後繼續繼續 ... 直到最右邊那一項左移若干次之後變成 0 ... 你就實現了完全不用加號的加法 ...

在這個時候 ... 你加上一個新的數字 ... 就實現了一個加號的三個數字相加 ...

當然如果你仍然願意繼續的話 ... 甚至可以實現不用加號的三個數字相加 ...

唯一的問題就是最終的式子會長到一個螢幕都顯示不下 ... 各種沒法看 ...

所以我們現在迴歸最初 ... 繼續列豎式 ... 看看三個數相加的時候到底發生了什麼 ...

我們再隨便挑三個數字 ... 比如 111 222 和 333 ...

   ""#""##''   0001101111  = 111   0011011110  = 222 + 0101001101  = 333--------------   1010011010  = 666

和之前一樣 ' 表示由原來的數字產生的進位 ... " 表示由 ' 產生的進位
...

新增的 # 表示原來的數字在這裡會產生進位但由於 ' 或 " 的原因發生了左移的進位位置
...

我們同樣把這個進位表示為二進位 ... ' 和 # 記為
1 其他記為 0 ... 如下 ...

   0001101111  ( a   0011011110  ( b   0101001101  ( c   0010011110  ( d

我覺得都到現在了 ... 不用我說你應該也可以看出規律了吧 ...

只要 a b c 三個數位某一位至少有兩個為 1 ... 在 d 的相應位置的左邊一位就為 1 ...

用式子來描述就是 d = ( ( a & b ) | ( b & c ) | ( a & c ) ) << 1 ...

| 是位元運算操作符裡面的 按位或 ...
對比三個數字找到是否有某兩個數位同一位都為 1 ...

進位算出來之後 ... 不考慮進位的計算結果是什麼就不用我說了吧 ..?

現在再回去看看最開始說過的那個公式 ... 是不是覺得豁然開朗了呢 ..?

終於寫完了 ... 這個回答寫了快兩個小時 ... 最後寫的頭都大了 ... 完全不知道自己在說什麼了已經 ...

答案裡不一定都對 ... 有錯誤的地方歡迎指正 ... 

教導小朋友果然是體力活 ... 求安慰 ...

以及 ... 最後給你留一道思考題 ... 你要是能做出來的話也不枉我費了這麼大力氣寫了這麼多 ...

實現不用乘號的兩個數相乘 ... 如果你能做出來就是真明白了 ...

恩恩就是這樣啦 ...

轉載自:http://nodejs.iteye.com/blog/1855220

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.