【算法學習】位操作1

位操作有太多的神奇寫法,這裏總結一部分。

1. 無算術運算符的加法 Add two numbers without using arithmetic operators

(1) 題意

如果有一個題目,要求我們實現一個 add 函數,不使用包括 +,++,-,--,.. 等算術運算符,完成兩個整型數的相加。

兩個比特的相加,可以用 ^ 來代替(可能存在進位);進位一個比特,可以用 & 來實現。類似的,數字邏輯中,完成兩個單獨的比特相加的是半加器(half adder) ,通過半加器的串聯,可以實現全加器。

一個樸素的思維是,從最高位開始,xy 的每一位相異或 ^ ,如果有進位,則對結果的高位異或 1 ,有進位就繼續。或者從最低位開始?這樣想太麻煩了。

(2) 思路

我們直接對 xy 進行操作,相當於並行進位。

(1) 如果 xy 在每一個二進制位都不同,x^y 就是 x+y 。如:0101 ^ 1010 = 1111

(2) 如果存在相同的二進制位(都是 1),那麼需要用 & 來將其吸納進去。都是 0 的情況無關緊要。

x = 7 = 0000 0111
y = 5 = 0000 0101
x+y   = 0000 1100

x=x^y = 0000 0010  //x^y爲0的二進制位代表的x,y對應位可能都是0, 或都是1
c=x&y = 0000 0101  //x&y爲1的二進制位標記出x,y對應位都是0的情況, 這代表這些位都需要進位
//進位: y = c << 1 = 0000 1010, 即準備對這些位的高一位進行“加法”
//加法的^, 遞歸進行
x=x^y = 0000 1000
c=x&y = 0000 0010
//進位: y = c << 1 = 0000 0100
//加法的^
x=x^y = 0000 1100  //此時x和y在每一個二進制位都不同
c=x&y = 0000 0000 //c=x&y=0, 不用再進位

(3) 模板代碼

下面的寫法可以作爲模板。

// C++ Program to add two numbers without using arithmetic operator  
#include <bits/stdc++.h> 
using namespace std; 
	
int add(int x, int y) {
	//iterate utill there is no carry
	while (y) {
		//the carry contains all the common bits of x and y 
		int carry = x & y; 
		//now, x is the SUM of bits of x and y
		//where at least one of the bits is not set 
		x = x ^ y;
		//carry is right-shifted by 1 so that adding it to x
		y = carry << 1;
	}
	return x;
}

int main() {
	cout << add(15, 32);
	return 0;
}

在這裏插入圖片描述
遞歸版:

int add(int x, int y) {
	if (y == 0) return x;
	return add(x ^ y, (x & y) << 1);
}

(3) 習題

POJ 1001 A + B Problem .

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章