1. 程式人生 > >來談談C++ 位運算 & | > ^ ~ %

來談談C++ 位運算 & | > ^ ~ %

老實說,我對+ = * / % && || ==一些比較簡單的運算子比較熟悉。對位運算就陌生了,主要用的少。我覺得高手用的會比較多,因為位運算速度比較快。

1.&

如果兩個相應的二進位制位都為1,則該位的結果值為1;否則為0。

注:下面都用8位的 unsigned char 來做例子。

&簡單舉例:

11&3  = 3

     00001011

&   00000011

=   00000011 = 3

&比較實用的例子:

比如我們經常要用的是否被2整除,一般都寫成   if(n % 2 == 0)

可以換成 if((n&1) == 0)

2. |

如果兩個相應的二進位制位只要有一個是1,結果就是1;否則為0。

| 簡單例子:

11 | 3 = 11

     00001011

|    00000011

=   00001011 = 11

| 比較實用的例子

可以用一個unsigned int 來儲存多個布林值。比如一個檔案有讀許可權,寫許可權,執行許可權。看起來要記錄3個布林值。我們可以用一個unsigned int也可以完成任務。

一個數r來表示讀許可權,它只更改個位來記錄讀許可權的布林值

00000001  (表示有讀許可權)

00000000  (表示沒有讀許可權)

一個數w表示寫許可權,它只用二進位制的倒數第二位來記錄布林值

00000010 (表示有寫許可權)

00000000 (表示沒有寫許可權)

一個數x表示執行許可權,它只用倒數第三位來記錄布林值

00000100 (表示有執行許可權)

00000000 (表示沒有執行許可權)

那麼一個檔案同時沒有3種許可權就是

~r | ~ w | ~ x 即為 00000000,就是0

只有讀的許可權就是

r | ~w | ~x 即為 00000001,就是1

只有寫的許可權就是

~r | w | ~x 即為 00000010,就是2

...

一個檔案同時有3種許可權就是

r | w | x 即為 00000111,就是7

3. << 向左移位移

<<簡單例子(向左移一位,右邊自動補0)

11 << 1 = 22

  00001011 << 1

  00010110 = 22

相當於二進位制的每個數都變成當前值的兩倍,結果就是變成當前值的兩倍。

n * 2 == (n << 1)

推廣下就是(注意可能會溢位)


4. >> 向右位移

>>簡單例子(向右移一位,左邊自動補1)

11 >> 1 =  5

00001011 >> 1

00000101 = 5

注意到最後一位的1被幹掉了。

比較實用的例子是:

int n = n / 2     等價於   int n = n >> 1  等價於 int n >>= 1

5. ^ 異或

兩個相同的數會變成0,反之是1

例子:

11^3 = 8

     00001011

^   00000011

=   00001000 = 8

我覺得理解異或,一定要用異或來解下面的題目:

Given an array of integers, every element appearstwice except for one. Find that single one.

就是一個數組中,所有數字都出現了兩次,只有一個沒有

比如 int t = {1,2,3,3,2,1,5} 要找到5。

用異或就完美了,所有相同的都會消失,留下來的就是5了。我發現異或是嫉妒成雙成對的。

int singleNumber(int A[], int n) {  
        for(int i = 1; i < n; ++i){  
           A[0] ^= A[i];  
        }  
        return A[0];  
    } 


還有就是用不tmp值來交換兩個數

//不用temp交換兩個整數
void swap(int& x , int& y)
{
	x ^= y;
	y ^= x;
	x ^= y;
} 

扯點別的,^在lua中表示pow的意思,這是要逆天。

6 ~

這個在加法中用到

x-y = x + ~y + 1

所以~y = - y  -1

比如 ~11 = -11 -1 = -12

7 再扯下%

居然有道題目是這樣的: 求 100 % 8的 優化解法。我們知道:


8剛好是2的3次方

所以 100 % 8 == 100 - math.floor(100 / 8) * 8 == 100 -  ((100 >> 3) << 3)

8.位運算優先順序

總的來說比較低,一定要加括號。