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

转载 2015年07月10日 16:27:19
求一个unsigned int 数的二进制表示中有多少个1?
 

第一种是很容易想到的采用循环的方式并且与1进行位与运算,具体代码如下:

 1unsigned int GetBitNumOfOne_ByLoop1(unsigned int nValue)
 2{
 3 const unsigned int nNumOfBitInByte = 8;
 4 unsigned int nBitMask = 1;
 5 unsigned int nBitNum = 0;
 6 for(unsigned int i = 0 ; i < sizeof(nValue) * nNumOfBitInByte ; i++)
 7 {
 8  (0 < (nValue & nBitMask)) ? nBitNum++ : 0;
 9  nBitMask<<=1;
10 }

11 return nBitNum;
12}

13unsigned int GetBitNumOfOne_ByLoop2(unsigned int nValue)
14{
15 const unsigned int nNumOfBitInByte = 8;
16 unsigned int nBitMask = 1;
17 unsigned int nBitNum = 0;
18 for(unsigned int i = 0 ; i < sizeof(nValue) * nNumOfBitInByte ; i++)
19 {
20  (0 < (nValue & nBitMask)) ? nBitNum++ : 0;
21  nValue>>=1;
22 }

23 return nBitNum;
24}

这两种做法很相像,却别就是在是对nBitMask进行左移还是对nValue进行右移。
当然了以上的两个方法存在一个问题:不管如何这个函数肯定要循环32次(对于32平台来说)。
那又没有更好的方法?当然有,请看下面:

 1unsigned int GetBitNumOfOne_ByLoop3(unsigned int nValue)
 2{
 3 unsigned int nBitNum = 0;
 4 while(0 < nValue)
 5 {
 6  nValue &=(nValue - 1);
 7  nBitNum++;
 8 }

 9 return nBitNum;
10}
假如使用参数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的个数。
上面的做法已经很不错了,但是作为程序员的你是否会有疑问,“还有其他的方法吗?”。
有,当然有!请看下面的代码:


 1unsigned int GetBitNumOfOne(unsigned int nValue)
 2{
 3 nValue = ((0xaaaaaaaa & nValue)>>1+ (0x55555555 & nValue);
 4 nValue = ((0xcccccccc & nValue)>>2+ (0x33333333 & nValue);
 5 nValue = ((0xf0f0f0f0 & nValue)>>4+ (0x0f0f0f0f & nValue);
 6 nValue = ((0xff00ff00 & nValue)>>8+ (0x00ff00ff & nValue);
 7 nValue = ((0xffff0000 & nValue)>>16+ (0x0000ffff & nValue);
 8 
 9 return nValue;
10}


假如你是第一次看到这些代码,你是否能看明白?呵呵,本人第一次看到这些代码的时候看了好久才感觉
好像有点明白。下面我就以一个例子来说明上面的代码是如何做到的。
假如参数是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组合起来是不是
0x10101010101010101010101010101010

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

然后0x00100010001000100010001000100010 & 0x00100010001000100010001000100010
得到0x01000100010001000100010001000100
我们把得到的结果分成8组0x0100 0100 0100 0100 0100 0100 0100 0100
每组的0100单独来看是不是十进制的4 总共有多少个4?是不是8个,8×4=32。

以下的代码:
 nValue = ((0xf0f0f0f0 & nValue)>>4) + (0x0f0f0f0f & nValue);
 nValue = ((0xff00ff00 & nValue)>>8) + (0x00ff00ff & nValue);
 nValue = ((0xffff0000 & nValue)>>16) + (0x0000ffff & nValue);
请自己按照上面的方法做一遍,就会发现规律:第一次32位数分成32组,第二次分成16组,第三次分成8,第四次分成4,第五次分成2组。
 

本文为转载 http://www.cppblog.com/OnTheWay2008/archive/2010/03/24/110467.html



输入一个整数,求该整数的二进制表示中有多少个1

求一个整数的二进制中1的个数。      题目:输入一个整数,求该整数的二进制表达中有多少个1。例如输入10,由于其二进制表示为1010,有两个1,因此输出2。       分析:这是一...
  • zhaojian3513012
  • zhaojian3513012
  • 2015年06月20日 13:01
  • 1283

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

这是一道面试题可以用以下的一些方案。 第一种是很容易想到的采用循环的方式并且与1进行位与运算,具体代码如下。  1int 数的二进制表示中有多少个1?" title="求一个unsigned ...
  • wyhang0
  • wyhang0
  • 2014年08月03日 11:47
  • 480

快速的判断一个数的二进制中有多少个1

x=x&(x-1)   表达式的意思就是:把x的二进制表示从低位开始,将遇到的第一个为1的比特位 置0。 例如: e1: x = 01001000 x-1 = 01000111 x&(x-1)...
  • qq_20801369
  • qq_20801369
  • 2016年09月03日 19:11
  • 2304

位操作:一个整数的二进制表示中 有多少个1?

#include int countHowMuchOne( int number ) { int count = 0; while ( number ) { number = numbe...
  • kennyrose
  • kennyrose
  • 2012年04月25日 19:16
  • 2474

输入一个整数,求该整数的二进制表达中有多少个1。例如输入10,由于其二进制表示为1010,有两个1,因此输出2。

题目:输入一个整数,求该整数的二进制表达中有多少个1。例如输入10,由于其二进制表示为1010,有两个1,因此输出2。 利用位运算~第二种思路很赞.... ? ...
  • luyuncsd123
  • luyuncsd123
  • 2014年07月19日 01:59
  • 1645

Lintcode 二进制中有多少个1

计算在一个 32 位的整数的二进制表式中有多少个 1. 您在真实的面试中是否遇到过这个题?  Yes 样例 给定 32 (100000),返回 1 给定 5 (101),返回 2 给...
  • Hk_john
  • Hk_john
  • 2017年04月17日 15:38
  • 435

32位整数的二进制表示中有多少个1

思路1:def countOnes(self, num): # write your code here if num < -2147483648 or num > 2...
  • u010510962
  • u010510962
  • 2016年03月17日 16:24
  • 1267

求一个整数中二进制1的个数

题目:求一个整数二进制表示1的个数   第一版: 思路:如果一个整数与1做与运算,结果为1,那么该整数最右边一位是1,否则是0; int NumberOf1(int n) { int c...
  • djb100316878
  • djb100316878
  • 2014年12月18日 08:55
  • 2745

nyoj题目100:1的个数

1的个数 时间限制:3000 ms  |  内存限制:65535 KB 难度:1 描述 小南刚学了二进制,他想知道一个数的二进制表示中有多少个1,你能帮他写一个程序来完成这个任务吗? ...
  • ojhawu
  • ojhawu
  • 2015年04月19日 13:00
  • 474

判断32位整数二进制中1的个数

在面试中被问到这一题:判断32位无符号整数二进制中1的个数,虽然不难,但要求层层优化。现在整理一下: 1、基本思路: #include iostream>  using namespace std; ...
  • lqk1985
  • lqk1985
  • 2008年05月22日 14:39
  • 1462
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:求一个unsigned int 数的二进制表示中有多少个1?
举报原因:
原因补充:

(最多只允许输入30个字)