今天ICS课上讲了两个很有趣的位运算技巧。
题目1,你要实现一个函数
unsigned leftmost(unsigned x);
返回x的最大一位1。
我们都知道最小可以用x&-x来实现,但是最大要怎么实现呢,感觉应该没有能够左右翻转的位运算。
所以基本可以用类似二分的做法来做。
然后老师给出了一种常数非常小的做法。
unsigned leftmost(unsigned x){
x|=x>>1;
x|=x>>2;
x|=x>>4;
x|=x>>8;
x|=x>>16;
return x&((x>>1)+1);
}
题目2
实现一个函数,判断x位的奇偶性。
还是用同样的方法
int evenones(unsigned x){
x^=x>>16;
x^=x>>8;
x^=x>>4;
x^=x>>2;
x^=x>>1;
return (x&1)^1;
}
题目3
求popcount(x),采用了分块的思想,分成8个大小为4的块
int popcount(int x){
int mask=(1<<4)+1;
mask|=mask<<8;
int mask2=(mask<<16)|mask;
int s=0;
s+=x&mask2;
s+=(x>>1)&mask2;
s+=(x>>2)&mask2;
s+=(x>>3)&mask2;
int mask3=3|(3<<16);
int ss=0;
ss+=s&mask3;
ss+=(s>>4)&mask3;
ss+=(s>>8)&mask3;
ss+=(s>>12)&mask3;
return (ss&31)+((ss>>16)&31);
}
上述代码可能存在问题(纯手打,没有测过),请大家以借鉴思路为主。