统计一个数二进制中1的个数
方法一
对求值对象先模2后除以2,直到其值为0,这个方法与"除2取余,逆序排列"进行十二进制转换的相同。缺点是这个方法有取模运算,所以只能统计正数,不适用于负数的统计。
u_int countOne1(int num)
{
u_int count = 0;
while (num)
{
if (num % 2==1){
count++;
}
num /= 2;
}
return count;
}
方法二
让该数和1>>31相与,判断最高位为1或者0,然后对该数进行左移,重复上面步骤,直到统计完32个比特位。这种方法无论求值对象有多少个1,循环都要执行32次,程序效率低。
u_int countOne2(int num)
{
u_int count = 0;
int flag = 1 << 31;
for (int i = 0; i < 32; i++)
{
if ((num<<i)&flag){
count++;
}
}
return count;
}
方法三
逐个消去最后一位的1,如下图,根据两个数相与的规律可以知道,一个数字的二进制序列和它本身的二进制序列-1相与,就会将该数最低的有1的比特位清成0。这种放法的好处是,二进制序列中有几个1循环就执行几次,程序效率高。
u_int countOne3(int num)
{
u_int count = 0;
while (num)
{
num&=num - 1;
count++;
}
return count;
}
完整代码
#include<stdio.h>
#include<windows.h>
#define unsigned int u_int
//方法一:模2除2
u_int countOne1(int num)
{
u_int count = 0;
while (num)
{
if (num % 2==1){
count++;
}
num /= 2;
}
return count;
}
//方法二:位运算
u_int countOne2(int num)
{
u_int count = 0;
int flag = 1 << 31;
for (int i = 0; i < 32; i++)
{
if ((num<<i)&flag){
count++;
}
}
return count;
}
//方法三:逐个消去最后一位的1
u_int countOne3(int num)
{
u_int count = 0;
while (num)
{
num&=num - 1;
count++;
}
return count;
}
int main()
{
int a = 1023;
u_int x = countOne1(a);
u_int y = countOne2(a);
u_int z = countOne3(a);
printf("%d %d %d\n", x,y,z);
system("pause");
return 0;
}