計算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)

 

 

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