Sword 位运算取余操作
/* 位运算取余操作 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> void test1() { unsigned a = 12; unsigned b = 7; unsigned c = 0; c = a % b; printf("----[%u]---\n", c); } void test2() { unsigned a = 12; unsigned b = 32; unsigned c = 0; /* 设计说明: 位运算取余必要条件 要求除数必须是2的幂次方 */ c = a & (b - 1); printf("----[%u]---\n", c); } int main() { test2(); getchar(); return 0; }
向上求一个数最近的2的整数次幂
// 方法一 static unsigned int _shared_dict_next_power(unsigned int size) { unsigned long i = 1; while (1) { if (i >= size) { return i; } i *= 2; } }
方法二
思路分析
2的n次方的二进制信息是如何表示的呢?他的二进制表现形式为,在第n位置上为1,其他位置全部为0。
例如 num的二进制是 10101001 ,那么距离num最近的2的n次方是多少呢?只需要把num的二进制最高位的1往前移动一位,也就是 100000000。
那么如何得到这个数呢?我们把100000000这个数减去个1来看下,得出的结果为011111111,这个数和num的二进制 10101001 最高位的1是一样的,只是右边全部为1。
那么接下来只需要把num的二进制信息最高位1右边变成1就可以了。
这里用到的是或运算,或运算的规则为1|1=1、1|0=1、0|0=0。
我们不知道num的数值是多少,他的最高位的1有可能在0~31位的任何位置,所以要做好最坏的打算。
第一轮
10101001 >> 1,即将最高位的1移动到次高位上,然后两数进行或计算,那么现在最高位和次高位肯定都是1
10101001 | (10101001 >> 1) = 11111101
第二轮
11111101 >> 2 目前最高位和次高位都是1,因此右移2,然后进行或运算,那么最高位加上后面3位肯定都是1
11111101 | (11111101 >> 2) = 11111111
按照这个思想,不断右移,进行与运算,当右移16时,基本上31都是1了
static unsigned int pow2roundup(unsigned int size) { // 防止遇到 size本身就是2的幂 size--; size |= size >> 1; size |= size >> 2; size |= size >> 4; size |= size >> 8; size |= size >> 16; return size + 1; }