1、用一个表达式,判断一个数X是否是2的N次方(2,4,8,16.....),不可用循环语句。
解析:X:2,4,8,16转化成二进制是10,100,1000,10000。如果减1则变成01,011,0111,01111。两者做按位与运算,结果如果为0,则X是2的N次方。
答案:!(X&(X-1))
2、统计一个整数的二进制中1的个数
int CountNumberOfOne(int number) { int counter = 0; while (number) { number &= number - 1 ; counter++; } return counter; }
3、对于集合的表示(类似于Bitmap,位图)
大多数时候,我们可以用一个整数来表示一个包含不超过32(当然如果使用64位整型变量也可以是64个)个元素的集合——对于每一个位,如果元素为1,则表示存在当前位所对应的集合成员,如果是0,则表示这个集合成员是不存在的。
比如A=1011 就可以表示集合{0,1,3},而上面提到的1<<x就表示集合{x}。
下面我们就能推导出一些直观的集合运算。
我们定义 ALL_BITS 为全集即各二进制位均为1的数。
集合的并 A|B
集合的交 A&B
集合的差 A& ~B
补集 ALL_BITS^A
添加特定元素bit A|=1<<bit
清除特定元素bit A^=1<<bit
取出特定元素bit A&=1<<bit
判断是否存在特定元素bit (A&1<<bit)!=0
4、元素交换,不使用第三个变量
swap(a, b) { a^=b; b^=a; a^=b; }
5、低位提取技术
我们对于一个非0数x,现在提取出其最低位的1。三种不同的写法。
Lowbit(x)=x&(x^(x-1))
Lowbit(x)=x&~(x-1)
Lowbit(x)=x&-x
注意:这里我们求出的是x中最后一个1表示的数,而非其位置。
可以发现,这三种低位函数的写法可谓大同小异——均涉及到了x&和x-1(其实 –x 可以认为是和 ~(x-1) 等价的,这里利用了负数的存储原理)。
x-1的性质在于:其将一个数最后一个1变成了0,并把原来这个1之后0的位置均变成了1。低位技术正是利用了这个性质。
参考资料:C语言中位运算的巧用