巧用位运算

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语言中位运算的巧用

posted @ 2013-10-06 09:57  虫不知  阅读(233)  评论(0编辑  收藏  举报