學會位運算,助力開發高性能

手撕位運算

0x00 -- 位運算概覽

符號 描述 運算規則
& 按位與, 2個位都爲1,結果爲1
按位或, 一個位爲1,結果爲1
^ 按位異或, 相同爲0,相異爲1
~ 按位取反, 1變0,0變1
<<n 左移 各二進位所有左移n位,高位丟棄,低位補0
>>n 右移 各二進位所有右移若干位,對無符號數,高位補0,有符號數,各編譯器處理方法不同,有的補符號位(算術右移),有的補0(邏輯右移)

0x01 -- 按位與 &

運算規則:0&0=0 0&1=0 1&1=1c++

倆位相同爲1,不然爲0markdown

3&5 = 1
3 0000 0011
5 0000 0101
& 0000 0001
複製代碼
用途
  • 清零

若是想將一個單元清0,即讓這個數的各個位都爲0,就讓這個數去與一個各位都爲0的數值按位與。結果爲0spa

  • 取一個數的指定位

舉個🌰:code

a = 1010 1110, 取a的低四位。只須要找一個b,把b的低四位設置爲1,其他爲0,即orm

b= 0000 1111 .編譯器

&= 0000 1110. 就能夠獲得a的指定部分, 這個過程當中b也就是a的(mask)所謂的掩碼。it

  • 判斷奇偶

只要根據末尾是0仍是1來判斷是不是奇偶數。io

是0就是偶數,是1就是奇數。所以能夠代替if (a % 2) == 0編譯

替換爲if(a&1==0)來判斷a是否爲偶數。table

0x02 -- 按位或 |

運算規則:0|0=0 0|1=1 1|1=1

只要其中一位是1, 結果就位1.

3|5 = 7
3 0000 0011
5 0000 0101
| 0000 0111
複製代碼
用途
  • 用來對一個數據的某些位設置位1

舉個🌰:

a = 1010 1110, 設置a的低四位爲1。只須要找一個b,把b的低四位設置爲1,其他爲0,即

b= 0000 1111 .

|= 1010 1111. 就能夠獲得按位與後的結果,

0x03 -- 按位異或 ^

運算規則:0^0=0 0^1=1 1^0=1 1^1=0

參加元算的倆個數,相同的位爲0,不一樣的位爲1;

異或的幾條性質:

  1. 交換律

  2. 結合律 (a^b)^c == a^(b^c)

  3. 對於任何數x,都有 x^x=0,x^0=x

  4. 自反性: a^b^b=a^0=a;

用途
  • 翻轉指定位

    舉個🌰:

    a = 1010 1110, 翻轉a的低四位。只須要找一個b,把b的低四位設置爲1,其他爲0,即

    b= 0000 1111 .

    ^= 1010 0001. 就能夠獲得按位異或後的結果。 就把a的低四位按位翻轉了。

  • 與0相異或值不變

    1010 1110
     0000 0000
    ^1010 1110
       a 3 0000 0011
       b 4 0000 0100
       a^b 0000 0111 a
       
       b 4 0000 0100
       b^a 0000 0111 a
       		 0000 0011 b
    複製代碼
  • 交換倆個數

    void swap(int a, int b) {
      if(a!=b) {
        a^=b;
        b^=a;
        a^=b;
      }
    }
    複製代碼

0x05 -- 按位取反 ~

運算規則: ~1=0 ~0=1

使a的最低位爲0,能夠表示爲:a & ~1。~1的值爲 1111 1111 1111 1110,再按"與"運算,最低位必定爲0。由於「 ~」運算符的優先級比算術運算符、關係運算符、邏輯運算符和其餘運算符都高。

0x06 -- 左移運算符 <<

使a的最低位爲0,能夠表示爲:a & ~1。~1的值爲 1111 1111 1111 1110,再按"與"運算,最低位必定爲0。由於「 ~」運算符的優先級比算術運算符、關係運算符、邏輯運算符和其餘運算符都高。

0x07 -- 右移運算符 >>

定義:將一個數的各二進制位所有右移若干位,正數左補0,負數左補1,右邊丟棄。

例如:a=a>>2 將a的二進制位右移2位,左補0 或者 左補1得看被移數是正仍是負。

操做數每右移一位,至關於該數除以2。

綜合應用

好比有兩個int類型變量x、y,首先要求x+y的和,再除以2,可是有可能x+y的結果會超過int的最大表示範圍,因此位運算就派上用場啦。

(x&y)+((x^y)>>1);


對於一個大於0的整數,判斷它是否是2的幾回方

`((x&(x-1))==0)&&(x!=0);


求絕對值

int abs( int x ) { 
   int y ; 
   y = x >> 31 ; 
   return (x^y)-y ;        //or: (x+y)^y 
}
複製代碼

取模運算,採用位運算實現:

a % (2^n) 等價於 a & (2^n - 1)


乘法運算 採用位運算實現

a * (2^n) 等價於 a << n


除法運算轉化成位運算

a / (2^n) 等價於 a>> n


求相反數

(~x+1)


a % 2 等價於 a & 1

相關文章
相關標籤/搜索