一个unsigned int 数的二进制表示中有多少个1

这是一道面试题能够用如下的一些方案。
第一种是很容易想到的采用循环的方式而且与1进行位与运算,具体代码以下。程序员

 1 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?unsigned int GetBitNumOfOne_ByLoop1(unsigned int nValue)
 2 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?{
 3 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? const unsigned int nNumOfBitInByte = 8;
 4 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? unsigned int nBitMask = 1;
 5 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? unsigned int nBitNum = 0;
 6 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? for(unsigned int i = 0 ; i < sizeof(nValue) * nNumOfBitInByte ; i++)
 7 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? {
 8 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?  (0 < (nValue & nBitMask)) ? nBitNum++ : 0;
 9 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?  nBitMask<<=1;
10 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? }
11 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? return nBitNum;
12 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?}
13 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?unsigned int GetBitNumOfOne_ByLoop2(unsigned int nValue)
14 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?{
15 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? const unsigned int nNumOfBitInByte = 8;
16 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? unsigned int nBitMask = 1;
17 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? unsigned int nBitNum = 0;
18 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? for(unsigned int i = 0 ; i < sizeof(nValue) * nNumOfBitInByte ; i++)
19 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? {
20 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?  (0 < (nValue & nBitMask)) ? nBitNum++ : 0;
21 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?  nValue>>=1;
22 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? }
23 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? return nBitNum;
24 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?}


这两种作法很相像,区别就是在对nBitMask进行左移仍是对nValue进行右移。
固然了以上的两个方法存在一个问题:无论如何这个函数确定要循环32次(对于32平台来讲)。
那又没有更好的方法?固然有,请看下面:面试

 1 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?unsigned int GetBitNumOfOne_ByLoop3(unsigned int nValue)
 2 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?{
 3 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? unsigned int nBitNum = 0;
 4 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? while(0 < nValue)
 5 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? {
 6 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?  nValue &=(nValue - 1);
 7 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?  nBitNum++;
 8 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? }
 9 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? return nBitNum;
10 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?}


假如使用参数12345(二进制是11000000111001)调用该函数,该函数的执行状况以下:
第一次进入循环
0 < 11000000111001
11000000111001 &= (11000000111001 - 1) 以后 nValue 的值是 11000000111000
nBitNum 的值是1
通过本次循环以后11000000111001 变成了 11000000111000 比以前少了一个1
第二次进入循环
0 < 11000000111000
11000000111000 &= (11000000111000 - 1) 以后 nValue 的值是 11000000110000
nBitNum 的值是2
通过本次循环以后11000000111000 变成了 11000000110000 比以前少了一个1
第三次进入循环
0 < 11000000110000
11000000110000 &= (11000000110000 - 1) 以后 nValue 的值是 11000000100000
nBitNum 的值是3
通过本次循环以后11000000110000 变成了 11000000100000 比以前少了一个1
通过以上3次循环状况的说明,我相信你必定看出了些什么吧。nValue &=(nValue -1),这句
代码实际上就是把nValue 的某位及其之后的全部位都变成0,当nValue最后变成0的时候循环结束,
且nBitNum 记录的就是1的个数。
上面的作法已经很不错了,可是做为程序员的你是否会有疑问,“还有其余的方法吗?”。
有,固然有!请看下面的代码:函数

 1 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?unsigned int GetBitNumOfOne(unsigned int nValue)
 2 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?{
 3 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? nValue = ((0xaaaaaaaa & nValue)>>1) + (0x55555555 & nValue);
 4 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? nValue = ((0xcccccccc & nValue)>>2) + (0x33333333 & nValue);
 5 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? nValue = ((0xf0f0f0f0 & nValue)>>4) + (0x0f0f0f0f & nValue);
 6 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? nValue = ((0xff00ff00 & nValue)>>8) + (0x00ff00ff & nValue);
 7 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? nValue = ((0xffff0000 & nValue)>>16) + (0x0000ffff & nValue);
 8 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? 
 9 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1? return nValue;
10 求一个unsigned <wbr>int <wbr>数的二进制表示中有多少个1?}


假如你是第一次看到这些代码,你是否能看明白?呵呵,本人第一次看到这些代码的时候看了很久才感受
好像有点明白。下面我就以一个例子来讲明上面的代码是如何作到的。
假如参数是0xffffffff。
第一行代码:
nValue = ((0xaaaaaaaa &nValue)>>1) + (0x55555555& nValue);
a的二进制表示是:1010
5的二进制表示是:0101
0xffffffff 与 0xaaaaaaaa进行与运算以后是0x10101010101010101010101010101010
而后再进行左移操做后是0x01010101010101010101010101010101
0x55555555 & nValue进行与运算以后是0x01010101010101010101010101010101
而后0x01010101010101010101010101010101 &0x01010101010101010101010101010101
获得0x10101010101010101010101010101010
咱们把获得的结果分红16组0x10  10 10  10  10 10  10  10 10  10  10 10  10  10 10  10
每组的10单独来看是否是十进制的2
咱们0x01010101010101010101010101010101和0x01010101010101010101010101010101这两个数也按照上面的方法分红
16个组0x01  01 01  01  01 01  01  01 01  01  01 01  01  01 01  01
     0x01  01  01 01  01  01 01  01  01 01  01  01 01  01  01 01
那么这两个数的每个组都是01 那么两个01里面有几个1,是否是2个。这是2是否是二进制的10,而后16个10组合起来是否是
0x10101010101010101010101010101010oop

第二行代码:
nValue = ((0xcccccccc &nValue)>>2) + (0x33333333& nValue);
此时nValue是0x10101010101010101010101010101010
c的二进制表示是:1100
3的二进制表示是:0011
0xcccccccc 与 nValue)进行与运算以后是0x10001000100010001000100010001000
而后再进行左移操做后是0x00100010001000100010001000100010
0x33333333 & nValue进行与运算以后是0x00100010001000100010001000100010.net

而后0x00100010001000100010001000100010 &0x00100010001000100010001000100010
获得0x01000100010001000100010001000100
咱们把获得的结果分红8组0x0100 0100 0100 0100 0100 0100 0100 0100
每组的0100单独来看是否是十进制的4 总共有多少个4?是否是8个,8×4=32。blog

如下的代码:
 nValue = ((0xf0f0f0f0 &nValue)>>4) + (0x0f0f0f0f& nValue);
 nValue = ((0xff00ff00 &nValue)>>8) + (0x00ff00ff& nValue);
 nValue = ((0xffff0000 &nValue)>>16) + (0x0000ffff& nValue);
请本身按照上面的方法作一遍,就会发现规律:第一次32位数分红32组,第二次分红16组,第三次分红8,第四次分红4,第五次分红2组。
若是仍是不明白请多看看,而后多选择几个参数进行试验,多试几回确定会明白的。get

 

转自:一个unsigned int 数的二进制表示中有多少个1it

相关文章
相关标签/搜索