【算法】解析位運算

位運算符是做用於整數的運算對象,把運算對象當作二進制的集合。測試

運算符 功能 用法
~ 按位求反 ~expr
<< 按位左移 expr1 << expr2
>> 按位右移 expr1 >> expr2
& 按位與 expr1 & expr2
^ 按位異或 expr1 ^ expr2
| 按位或 expr1 | expr2


按位求反(~)
將運算對象的二進制逐位求反,將1置爲0,將0置爲1,後獲得一個新的值。ui

int j = 10;
cout << (~j) << endl;//-11


按位左移(<<)
將運算對象的二進制位往左移動n位,右邊以數字0補充空出來的二進制位,後獲得一個新的值。一個數m往左移動n位後(移動的範圍在容器的範圍內),那麼新的值將會是m*2nspa

int j = 10;
cout << (j << 2) << endl;//40


按位右移(>>)
將運算對象的二進制位往右移動n位,左邊以0或1補充,具體的實現規則要根據具體的環境而定。一般狀況下,如果負數那麼左邊補充1,如果正數那麼左邊補充0。一個浮點數m往右移動n位後,那麼新的值將會是floor(m / 2n),其中floor(x)返回一個小於或等於浮點數x的最大的整數。code

int j = 10;
cout << (j >> 2) << endl;//2
j = -10;
cout << (j >> 2) << endl;//-3


按位與(&)
將兩個運算對象的二進制逐位執行與的邏輯操做,只有兩個相同位置都是1,結果纔是1;不然是0。對象

int j = 10;
int i = 3;
cout << (j & i) << endl; //2


按位或(|)
將兩個運算對象的二進制逐位執行或的邏輯操做,兩個相同位置只要有一個是1,結果就是1;不然爲0。blog

int j = 10;
int i = 3;
cout << (j | i) << endl; //11


按位異或(^)
將兩個運算對象的二進制逐位指向異或的邏輯操做,兩個位相同,結果爲0;不然爲1。table

int j = 10;
int i = 3;
cout << (j ^ i) << endl; //9


口訣:class

按位與(&),兩個都是1,纔是1。
按位或(|),只要有一個爲1,就是1。
按位異或(^),相同的爲0,不一樣的爲1。


位運算符的使用案例
假設班級中有30個學生,老師每週都會對學生進行一次小測試,測試結果只有經過和不經過兩種。咱們用二進制位表明某個學生在一次測試中是否經過,顯然全班學生能夠用一個無符號整數來表示:容器

unsigned long quiz1 = 0;

這裏之因此使用long而不是用int,是由於long在每臺機器上至少都有32位(有30個學生,能夠知足要求),而int不能保證在每臺機器上都有32位(int的最小大小是16位)。

教師必須有權檢查每個二進制位。例如:咱們須要對序號爲27的學生進行對應的位設置,以表示它經過測驗。爲了達到這一目的,首先建立一個值,該值只有第27位是1,其它位是0,而後再將這個值與quiz1進行或運算,這樣就能將quiz1的第27位設置爲1,其它位不變。
爲了實現這個目的,須要使用左移運算符和一個unsigned long類型的整數字面值1就能獲得學生第27號學生經過檢測的數值:二進制

1UL << 27;//UL 是unsigned long類型


接下來與quiz1進行或運算:

quiz1 |= 1UL << 27;//將第27位改成1(經過測試)


假設在從新覈對測試結果後發現第27號學生並無經過測試,他必須將第27位置爲0。此時須要一個特殊的整數,它的第27位是0,其它位是1,而後將這個值與quiz1進行安位與運算,所得結果除了第27位變成0,其它位都沒變。

quiz1 &= ^(1UL << 27);//將第27位改成0(未經過測試)


最後,咱們試圖檢測第27位學生的測試狀況到底怎麼樣:

bool status = quiz1 & (1UL << 27);

若是quiz1的第27位是1,那麼計算結果就是非0(真),不然結果是0。

相關文章
相關標籤/搜索