聊聊使用位運算來實現加法(老物)


好久沒寫資料了,一方面是現在要寫的東西太多,思考的事情也太多,都沒什么時間來坐下來整理一下有趣的資料出來(其實還是因為自己太懶。)

今晚偶然間看到有人問起了不用內置 + 運算符怎么實現 + 法,這個問題讓我想起了不用比較運算符( < 、 > 、 = )怎么實現比較,其實都不是問題,用我的理解方式去理解其實就是一個小學的問題 = -= 。

那按我前面所說的就設置一個最終目標吧。

如何從零開始實現一個比較運算符。

(顯然今天這篇是講不到最終目標了,也許以后也講不到了,不過看完這篇文章后,你應該就知道怎么做了。)

首先我們先在數學上講得通道理,再拿到計算機里面看着實現,比較這事情呢,主要就看與 0 的結果。
比如:a > b => a - b > 0,那我們只需要知道 (a - b) 的結果的正負號就可以做出比較的結果了。
所以我們得有正負數的定義吧,然后還得有(a - b)的減法實現吧。
那么如何實現減法呢?一個正數加上一個負數是不是就有了減法呢?確實是。
所以今天的主題就回到標題上,只要有了加法,那就會有了減法,同樣也會有乘法,甚至就會有了比較運算,就如上解釋可知。

小時候,我們最早計算 9 + 11 的時候是這樣算的。

	  11
	+  9
	-------
	  20

沒錯吧,這個我認為中國人都應該知道的吧,自行百度 豎式計算 。
其實,這個在二進制數中也是可行的,而上面那個是十進制的,二進制的就叫逢二進一。

	  11    =>        1011
	+  9    =>    +   1001
	-------        --------
	  20             10100

這個結果你能接受的話,那我們就進入到代碼實現部分吧。

對於二進制的豎式計算中存在兩個邏輯,分別是 進位 和 合並 。
進位指對列同為 1 的執行逢二進一,合並指對列不同數值的執行為 1 。
以上邏輯將分別用二進制運算來取代,前者可以視為按位與(&)和左移一位,后者可以視為兩數執行按位或。
我附加一點二進制運算說明吧。

在位運算中 ^ 和 & 分別產生以下結果。

	  1011
	^ 1001
	---------     
	  0010

數學意義為,模擬逢二進一的相加結果,保留未進位的結果,這是為了模擬豎式計算的加法結果。
(因為同為 1 則進位,同為 0 無結果,最終結果都是要將其變為 0 ,則可以理解為進位后的結果。)

	  1011
	& 1001
	---------     
	  1001

數學意義為,標記所有進位位置,對其執行 << 1 即可得到進位的結果。

以 1011 + 1001 為例:

根據豎式運算可知:

	  1011  // 
	+ 1001  // 
	---------
	 00010  // 先 1011 ^ 1001 合並得到未進位的結果( 1011 ^ 1001 = 00010 )
	 10010  // 1011 & 1001 = 1001 不為 0 存在進位,故執行 1001 << 1 得到進位后的結果 1001 
	---------
	 10000  // 通過 00010 ^ 10010 合並得到未進位的結果( 00010 ^ 10010 = 10000 )
	 00100  // 00010 & 10010 = 00010 不為 0 存在進位,故執行 00010 << 1 得到進位后的結果 00100 
	---------
	 10100  // 通過 10000 ^ 00100 合並得到未進位的結果( 10000 ^ 00100 = 10100 )
	 00000  // 10000 & 00100 = 00000 ,此時結束運算。
	---------

合並(^)結果后檢查是否為可進位(&),直到最終不存在可進位的數,則說明加法結束。

最后貼個代碼。

uint add(uint a, uint b)
{
	uint sum, carry;
	while(1)
	{
		sum = a ^ b, carry = a & b;
		if(0 == carry) 
	{
		break;
	}
		a = sum, b = carry << 1;
	}
	return sum;
}

uint Add(uint a, uint b)
{
	uint sum = a ^ b, carry = a & b;
	return (0 != carry) ? Add(sum, carry << 1) : sum;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM