输入一个整数,求该整数的二进制表达中有多少个'1'。例如输入10,由于其二进制表示为1010,有两个'1',因此输出2。
#include <iostream>
using namespace std;
/**********************************************************************************
方法一:判断一个整数n的二进制表示中每一位是否为'1',如果为'1',就在count上加1,循环
次数为常数,即n的二进制位数。但是该方法有一个缺陷,就是在'1'比较稀疏的时候效率较低。
***********************************************************************************/
int NumberOf1_Solution1(int n)
{
int count=0;
while(n != 0)
{
if(n & 0x01u)
count++;
n>>=1;
}
return count;
}
/**********************************************************************************
上面的方法存在一个问题,那就是当n为负数的时候,程序会进入死循环,因为如果n为负数,
n左移高位是补'1',因此最后n的二进制位会变成全'1'。下面作如下的改进:
将n和无符号数1按位与,判断n的二进制最低为是否为'1',然后将1左移一位,判断n的二进制
次最低为是否为'1',如此循环可求出n的二进制表达中有多少个'1'。
**********************************************************************************/
int I_NumberOf1_Solution1(int n)
{
unsigned int flag=1;
int count=0;
while(flag != 0)
{
if((n & flag) != 0)
count++;
flag<<=1;
}
return count;
}
/***********************************************************************************
方法二:以上方法的循环次数为常数,即n的二进制位数,且在'1'比较稀疏的时候效率较低。
我们可以改进,先介绍一下n&(n-1)的结果的含义,例如n=14,二进制为1110,n-1=13(1101),
n&(n-1)=(1110)&(1101)=1100,我们发现n&(n-1)的结果即是将n的二进制数的最低位'1'变成
'0',又例如(1100)&(1100-1)=(1100)&(1011)=1000,我们同样可以得出以上结论。利用该性质
得出方法二的代码如下:
***********************************************************************************/
int NumberOf1_Solution2(int n)
{
int count=0;
while(n != 0)
{
count++;
n=n&(n-1);
}
return count;
}
int main()
{
int n=10;
cout<<NumberOf1_Solution1(n)<<endl;
//cout<<NumberOf1_Solution1(-n)<<endl;//会进入死循环
cout<<I_NumberOf1_Solution1(n)<<endl;
cout<<I_NumberOf1_Solution1(-n)<<endl;
cout<<NumberOf1_Solution2(n)<<endl;
cout<<NumberOf1_Solution2(-n)<<endl;
system("pause");
return 0;
}