1. 程式人生 > >位運算——進階程式設計技巧

位運算——進階程式設計技巧

位運算即基於二進位制的運算,是直接對記憶體資料進行處理的更符合計算機系統的運算。眾所周知,計算機系統是基於二進位制的,若我們能夠在程式設計的時候使用位運算,則計算機能夠更加容易“讀懂”,從而大大提高程式碼執行速度。
雖然位運算與我們日常經常接觸的十進位制的運算不同,可能會難以理解,但是為了進一步優化程式碼,我們必須去嘗試使用位運算代替部分程式碼。位運算是前人留給我們的巨大的財富和強大的武器。

本文將介紹位運算的型別以及位運算的一些簡單的例子。

位運算型別

  1. 與&
    只有1&1 = 1,其他與運算結果為0,即0&1 = 0;1&0 = 0;0&0 = 0。

  2. 或|
    只有0|0 = 0,其他或運算結果為1,即0|1 = 1 ;1|0 = 1;1|1 = 1。

  3. 非~
    ~0 = 1,~1 = 0。

  4. 異或^
    異或即不同為1,相同為0。即0^0 = 0 1^1 = 0 0^1 = 1 1^0 = 1。

  5. 左移<<
    將二進位制數左移n位,低位補0.如下表所示:
    | 左移前 | 0010 1000 |
    | >>3 | 0100 0000 |
    | >>1 | 1010 0000 |

  6. 右移>>
    將二進位制數右移n位,若為負數,高位補1;否則,高位補0.
    | 右移前 | 0010 1010 | 1010 1010 |
    | >>2 | 0000 1010 | 1110 1010 |

程式碼示例

一些有用的小例子~

  • 求兩個整數的平均值

&將兩個數一樣的部分提出來一半,異或將兩個數不一樣的數提出來了,再右移一位,相當於提出來了一半,將他們相同的和不相同各提出來一半就是平均數。

int avg(int x,int y)
{
    /*位運算求兩個整數的平均值*/
    return (x & y) + ((x^y)>>1);
}

一行程式碼搞定~

  • 求一個整數的絕對值
int abs(int x)
{
    int y = x>>31;//x為正數,則y = 0 ; x 為負數 則 y = -1;
return ((x^y)-y); }
  • 交換兩個數
int swap(int *a,int *b)
{
    (*a) ^= *b;
    (*b) ^= *a;
    (*a) ^= *b;
    return 0;
}

  • 一些複雜點的例子
unsigned setbits(unsigned x,int p,int n, unsigned y)
{/*將X中從第p位開始的n各位設定為y中最右邊n位的值,x的其餘各位保持不變*/
    return x&~(~(~0<<n)<<(p+1-n))||(y&~(~0<<n)<<(p+1-n));
}


unsigned invert(unsigned x,int p,int n)
{/*將x從第p位開始的n個位求反,新的其餘各位保持不變*/
    return x^(~(~0<<n)<<(p+1-n));
}



unsigned rightrot(unsigned x,int n)
{/*將x迴圈右移(從最右端移出的位從最左端移入)n位後得到的值*/
    int wordlength = sizeof(x)*8;
    int rbit;
    if(n % wordlength > 0)
    {
        rbit = ~(~0 << n) & x << (wordlength - n);
        x = x >> n;
        x = x || rbit;
    }
    return x;
}