int bitCount(int x)
{
int mask1 = 0x55;
int mask2 = 0x33;
int mask3 = 0x0F;
int result = 0;
mask1 = mask1 | (mask1 << 8);
mask1 = mask1 | (mask1 << 16);
mask2 = mask2 | (mask2 << 8);
mask2 = mask2 | (mask2 << 16);
mask3 = mask3 | (mask3 << 8);
mask3 = mask3 | (mask3 << 16);
result = (x & mask1) + ((x >> 1) & mask1);
result = (result & mask2) + ((result >> 2) & mask2);
result = (result & mask3) + ((result >> 4) & mask3);
}
这里采用了一个很巧妙的方式统计一个二进制数里1的个数,我们先从一个简单的例子看起
如果是统计只有两位的二进制数,比如10,我们先将其和01相与得到00,然后将其向右移一位之后与01相与得到01,然后将其相加便得到10中含有1的个数。
int ilog2(int x)
{
int result=0;
int b4=!!(x>>16);
int b3=0;
int b2=0;
int b1=0;
int b0=0;
result = b4<<4;
b3 = !!(x>>(8 + result));
result |= (b3<<3);
b2 = !!(x>>(4 + result));
result |= (b2<<2);
b1 = !!(x>>(2 + result));
result |= (b1<<1);
b0 = !!(x>>(1 + result));
result |= b0;
return result;
}
此题的解体思路有点类似二分的思想,先将一个32位整型数分成高十六位和低十六位,如果高十六为有1存在,那么这个数至少比2^16大,那么我们接着看高十六位的低八位。如果高十六没有1存在,那么我们就需要看低16位的高八位,以此类推。
int logicalShift(int x, int n)
{
int mask=1;
mask<<=31;
mask>>=n;
mask<<=1;
mask=~mask;
x>>=n;
return x&mask;
}
这个题目主要利用移位的操作,计算机存储数据以补码的形式,所以算术右移的时候是补充的符号位,我们构造的mask就是前面是n个0,后面全是1即可。构造的方式就是先将一个1移到符号位,然后右移补充的都是1再进行取反操作就OK了,这里值得注意的是我们是先向右移动n次,再向左移动1次,这样我们就可以应对n=0的情况了。