1. 程式人生 > 其它 >位運算操作技巧

位運算操作技巧

使用位運算的注意事項:

  • 位操作只能用於整形資料,對float和double型別進行位操作編譯器會報錯。
  • 位操作符的運算優先順序比較低,儘量使用括號來確保運算順序。

注意:一般運算不一定比位運算慢。編譯器已經做的很好了,會把一般運算優化為位運算。

某些自作聰明的優化反而會誤導編譯器,使得編譯器不進行更棒的優化。


取第n位的值(從右邊)

int r = (v >> n) & 1;

把某一位置1(從右邊)

v = v | (1 << n);

把某一位取反(從右邊)

v = v ^ (1 << n);

把最後一個1置0

v = v & (v - 1);

把最後一個0置1

v = v | (v + 1);

奇偶判斷

(v & 1)

計算絕對值

int bits = sizeof(v) * 8 - 1;
int r = (v ^ (v >> bits)) - (v >> bits);

取模

//v % (2^n)可以轉化為去掉n位之前的值
int mod = v & (2^n - 1); 

乘2的n次方

int r = v << n;

除2的n次方

int r = v >> n;

除2的餘

int r = v & 1;

判斷語句 v == a ? b : a;

v = a ^ b ^ v;

否為2的冪

bool power2(int v){
    return ((v & (v - 1)) == 0) && (v != 0);
}

求整數的平均值

//第1部分:計算相同位的平均值
//第2部分:計算不同位的平均值
int average(int x, int y){    
    return (x & y) + ((x ^ y) >> 1);
}

判斷兩數符號是否相反

bool f = ((a ^ b) < 0);

根據掩碼mask合併a和b, mask為1的位為b的值,反之為a的值

unsigned int r = a ^ ((a ^ b) & mask);

計算二進位制v中1的個數n

int count_1(int v) {
    int n = 0;
    while (v) {
        n++;
        v &= (v - 1);
    }
    return n;
}

計算二進位制v中0的個數n

int count_0(int v) {
    int n = 0;
    while (v + 1) {
        n++;
        v |= (v + 1);
    }
    return n;
}

下一個2的冪次方

unsigned int nextpowerof2(register unsigned int x) {
    if (x == 0) {
        return 1;
    }
    x--;
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);
    return(x + 1);
}

上一個2的冪次方

unsigned int lastpowerof2(register unsigned int x) {
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);
    return(x & ~(x >> 1));
}

計算二進位制數字前導0的個數

int clz(unsigned int x) {
    if (x == 0) return 32;
    int e = 31;
    //1111 1111 1111 1111 0000 0000 0000 0000  
    if (x & 0xFFFF0000) { e -= 16; x >>= 16; }
    //0000 0000 0000 0000 1111 1111 0000 0000  
    if (x & 0x0000FF00) { e -= 8; x >>= 8; }
    //0000 0000 0000 0000 0000 0000 1111 0000  
    if (x & 0x000000F0) { e -= 4; x >>= 4; }
    //0000 0000 0000 0000 0000 0000 0000 1100  
    if (x & 0x0000000C) { e -= 2; x >>= 2; }
    //0000 0000 0000 0000 0000 0000 0000 0010  
    if (x & 0x00000002) { e -= 1; }
    return e;
}

refer:

https://www.cnblogs.com/xiaohutu/p/10951911.html