位运算操作技巧

使用位运算的注意事项:

  • 位操作只能用于整形数据,对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

posted @ 2022-05-17 18:31  天下太平  阅读(68)  评论(0编辑  收藏  举报