将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计数也是一样的