C语言统计一个数二进制中1的个数

统计一个数二进制中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;
}

猜你喜欢

转载自blog.csdn.net/qq_44631587/article/details/120519249