【C语言】写一个函数返回参数二进制中1的个数(附完整代码)

写一个函数返回参数二进制中1的个数
比如:15 00001111 4个1

主函数部分:
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第1张图片
想要得到二进制中1的个数,就需要逐个判断每个二进制位上的数是否为1,在这里我们可以参考十进制数得到每一位上的方法。
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第2张图片
二进制得到每一位上数的方法:
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第3张图片

可以知道,用十进制数除以2得到的余数就是二进制数最低位上的数。

number_of_1()函数部分:
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第4张图片
我们输入15时,输出4,正确。
但是,当我们输入-1时,输出了0,很明显,这个函数对负数的处理出现了问题。
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第5张图片
输入-1,输出0的原因
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第6张图片
输入-1应该是32才对
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第7张图片
如何解决呢,我们知道-1是以补码形式存储在内存中的,传给函数时是有符号的形式,我们可以将传参时的int m改为unsigned int m,改成无符号的形式即可。
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第8张图片
这个问题我们也可以用按位与&的方法解决。
以下方法可依次得到各二进制位上的数:
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第9张图片
测试一下,方法正确。
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第10张图片
利用这个方法,我们虽然可以解决问题,但是仍然还有改进的空间,比如循环次数过多,每次都要循环32次,会占用很多的内存空间,效率较低。
这里介绍一个方法:

利用表达式n=n&(n-1)
【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第11张图片
到n等于0时,表达式n=n&(n-1)执行过几次,就说明二进制数中有几个1。
可得代码:

【C语言】写一个函数返回参数二进制中1的个数(附完整代码)_第12张图片
拓展:判断一个数是不是2的幂次方。
分析:
2的0次方:1 0001
2的1次方:2 0010
2的2次方;4 0100
2的3次方:8 1000
.
.
.
.
要判断一个数是不是2的幂次方,就看二进制中是不是只有一个1。
在计算出count后再判断是否为1就行了。(代码略)

完整代码:

//写一个函数统计二进制位中1的个数

#include
//int number_of_1(unsigned int m)
//{
//	int count = 0;
//	while (m)
//	{
//		if (m % 2 == 1)
//			count++;
//		
//		m /= 2;
//	}
//	return count;
//}


//int number_of_1(int m)
//{
//	int count = 0;
//	int i = 0;
//	for (i = 0; i < 32; i++)
//	{
//		if (((m >> i) & 1) == 1)
//			count++;
//	}
//	return count;
//}


int number_of_1(int m)
{
	int count = 0;
	int i = 0;
	while (m)
	{
		m = m & (m - 1);
		count++;
	}
	return count;
}
int main()
{
	//-1
	//10000000000000000000000000000001 原码
	//11111111111111111111111111111110 反码
	//11111111111111111111111111111111 补码 --> 32
	int n = 0;
	scanf("%d", &n);//15
	int ret = number_of_1(n);
	printf("%d\n", ret);//4  1的个数
	return 0;
}```

你可能感兴趣的:(C,c语言)