计算32位整形数内含有1的个数

1.      目标:计算32位整形数内含有1的个数

2.      最原本的思想:将整形数对应的32位二进制数字中所有的1加起来就是所求的结果。

即:

7=0000-0000-0000-0000-0000-0000-0000-0111=0+0+…+0+1+1+1=3

3.      简化后的思想:逐次将相邻位的1相加,最后得到的总数就是要求的结果。

a)        7=0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-1-1-1

=>7=00-00-00-00-00-00-00-00-00-00-00-00-00-00-01-10

注释:相邻2位相加,实际上是1位加1位,得到相邻2位1的总和,为了防止得到的值溢出,在保证和不变的同时,将1位加1位的和用2位表示,仍然放在原来的位置上,不过此时,相邻2位表示的是一个值,应看作一个整体。

b)       7=00-00-00-00-00-00-00-00-00-00-00-00-00-00-01-10

=>7=0000-0000-0000-0000-0000-0000-0000-0011

    注释:相邻4位相加(相邻2个值相加),实际上还是1个值加1个值,得到相邻

4位1的总和,为了防止溢出,将1个值(2位)加1个值(2位)的和变为4位,仍然放在原来的位置上,不过此时相邻4位看作一个值,表示原来相邻4位中1的总和,应看作一个整体。

c)       7=0000-0000-0000-0000-0000-0000-0000-0011

=>7=00000000-00000000-00000000-00000011

注释:依次类推,相邻8位在原来4位的基础上相加,得到相邻8位1的总和,放在原来的位置上,不过此时相邻8位看作一个值,表示原来8位中1的总和,应看作一个整体参与下一次的运算中。

d)       7=00000000-00000000-00000000-00000011

=>7=0000000000000000-0000000000000011

注释:依次类推,相邻16位在原来8位的基础上相加,得到相邻16位1的总和,放在原来的位置上,不过此时相邻16位看作一个值,表示原来16位中1的总和,应看作一个整体参与下一次的运算中。

e)        7=0000000000000000-0000000000000011

=>7=00000000000000000000000000000011

注释:依次类推,相邻32位在原来16位的基础上相加,得到相邻32位1的总和,放在原来的位置上,不过此时相邻32位看作一个值,表示原来32位中1的总和,应看作一个整体参与下一次的运算中。

4.      利用掩码实现简化后的思想。

代码实现如下:

intCountBits(unsigned int x)

{

static unsigned int mask[] =

{

        0x55555555,

        0x33333333,

        0x0f0f0f0f,

        0x00ff00ff,

        0x0000ffff

};

int i; //计算循环次数以及取正确的掩码值

int shift;/*Number of positions to shift toright*///计算正确的右移位数,右移位数用于将高位移动到对应低位

for(i = 0, shift = 1; i< 5; i++,shift *= 2)

{

        printf("i = %d  shift = %d mask[i] = %d x=%d x>>shift = %d x= %d\n",i,shift,mask[i],x,x>>shift,

               (x & mask[i]) + ((x >>shift) & mask[i]));

        x = (x & mask[i]) + ((x >>shift) & mask[i]);

 

}

return x;

}

 

代码分析:

a)      i//计算循环次数以及取正确的掩码值

shift//计算正确的右移位数,右移位数用于将高位移动到对应低位

              循环0-4对应3中思想分析的a-e

       取x = 7;

       当i = 0,shift = 1 时,

x = 7=0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-1-1-1,

mask[0]=0x55555555=0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1-0-1

分析x = (x & mask[i]) + ((x >> shift) & mask[i]);

x & mask[0]将相邻2位中的高位全部置0,而低位的有效位全部保留了下来。

x>>shift将x所有位右移一位,即将相邻2位中的高位全部移动到了低位的位置上,同时保证了高位的有效位没有损失。

(x>>shift)&mask[0]将移动后的低位,即原来相邻2位中的高位有效位全部保留下来了。

x = (x &mask[i]) + ((x >> shift) & mask[i]);实现了相邻2位依次相加,并将值保留至原来相邻2位上的功能。

对应于3.a)

b)     当 i=1,shift = 1*2时,

x=7=00-00-00-00-00-00-00-00-00-00-00-00-00-00-01-10

       mask[1]=0x33333333=00-11-00-11-00-11-00-11-00-11-00-11-00-11-00-11

分析x = (x & mask[i]) + ((x >> shift) & mask[i]);

与4.a)类似,实现了相邻4位依次相加,并将值保留至原来相邻4位上的功能。

对应于3.b)

c)     当i=2, shift = 1*2*2时,

x=7=0000-0000-0000-0000-0000-0000-0000-0011

mask[2]=0x0f0f0f0f=0000-1111-0000-1111-0000-1111-0000-1111

分析x = (x & mask[i]) + ((x >> shift) & mask[i]);

与4.c)类似,实现了相邻8位依次相加,并将值保留至原来相邻8位上的功能。

对应于3.c)

d)     当i=3, shift = 1*2*2*2时,

x=7=00000000-00000000-00000000-00000011

mask[2]=0x00ff00ff=00000000-11111111-00000000-11111111

分析x = (x & mask[i]) + ((x >> shift) & mask[i]);

与4.d)类似,实现了相邻16位依次相加,并将值保留至原来相邻16位上的功能。

对应于3.d)

e)      当i=4, shift = 1*2*2*2*2时,

x=7=0000000000000000-0000000000000011

mask[2]=0x0000ffff=0000000000000000-1111111111111111

分析x = (x & mask[i]) + ((x >> shift) & mask[i]);

与4.e)类似,实现了相邻32位依次相加,并将值保留至原来相32位上的功能。

对应于3.e)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章