一些奇怪的位运算

Reading time ~2 minutes

将v上调至2的幂

    inline unsigned long long qNextPowerOfTwo(unsigned int v)
    {
        v |= v >> 1;
        v |= v >> 2;
        v |= v >> 4;
        v |= v >> 8;
        v |= v >> 16;
        ++v;
        return v;
    }

    inline unsigned long long qNextPowerOfTwo(unsigned long long v)
    {
        v |= v >> 1;    // 步骤1
        v |= v >> 2;    // 步骤2
        v |= v >> 4;    // 步骤3
        v |= v >> 8;
        v |= v >> 16;
        v |= v >> 32; 
        ++v;            //  最终
        return v;
    } 

基本思路:想要获取到2的幂那么只需要获取到最高位1的位置,然后向这个位置的右边全部置0,然后该位左移动一位即可获得。

而上面两个函数则是将该位的右侧全部置1,然后+1使得进位获得结果

即如:

初始:    1 0 0 0 0 0 0
步骤1:   1 1 0 0 0 0 0
步骤2:    1 1 1 1 0 0 0
步骤3:    1 1 1 1 1 1 1
...
最终:   1 0 0 0 0 0 0 0

将v上调至8的倍数

    const unsigned align = 8;
    unsigned int RoundUp(unsigned int v) 
    {
        return (v + align - 1) & ~(align - 1);
    }

基本思路:想要获得8的倍数,那么就要最后三位置0即可,即:v & ~(align - 1) 考虑到1-7要到8所以需要加上7即有:(v + align - 1)

统计v的二进制1和0的个数

    size_t countOneV1(int v) {
        size_t c = 0;
        while (v) 
        {
            if (v & 1) ++c;
            v >>= 1;
        }
        return c;
    }

    size_t countOneV2(int v) {
        size_t c = 0;
        while (v) 
        {
            ++c;
            v = v & (v - 1);
        }
        return c;
    }

    size_t countZero(int v) {
        size_t c = 0;
        while(v) 
        {
            ++c;
            v = v | (v + 1);
        }
        return c;
    }

基本思路:V1版本通过逐位与1遍历即可得到方便理解;V2版本在(v-1)时会有两种情况

1. 当前位是1,那么如 v = 101, v - 1 = 100 
2. 当前位是0,那么如 v = 100, v - 1 = 011

两种情况都会将最右的1给清0,所以每次都会消除一个1。同理对0计数也是一样的

Vm下Ubuntu编译Qt5.15遇到的坑

ubuntu20.0编译qt15.0踩过的坑 Continue reading

Rc4算法的实现

Published on March 30, 2021