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

一共介绍3种方法:

方法1:类似于前一篇文章中求一个数的每一位,不过上一篇是按十进制来的,简单来说就是 %10后 /10,求二进制的话类比,先%2后/2见下图

你可能会写下面的代码:

int count_num_of_1(int num)
{
	int count = 0;
	while (num)
	{
		if (num % 2 == 1)          // -1 % 2 = 0   count不自加
		{
			count++;
		}
		num = num / 2;            // -1 / 2 = 0 , num = 0 ,下一次不进入循环,直接返回0
	}

	return count;
}
#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);

	int n = count_num_of_1(num);

	printf("n = %d\n", n);

	return 0;
}

当然上面的代码求正数可以,求负数会出现错误,以-1为例,-1进入循环后,-1%2!=1,count不自加,直接执行-1/2=0,下一次就不进入循环了,直接输出count=0;改正的话将函数的形参改为unsigned int型,用无符号的整形去接收时,-1会被看成一个很大的正数,结果就正确了

正确代码如下:

int count_num_of_1(unsigned int num)   // -1会被当成一个很大的正数
{
	int count = 0;
	while (num)
	{
		if (num % 2 == 1)
		{
			count++;
		}
		num = num / 2;
	}

	return count;
}
#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);

	int n = count_num_of_1(num);

	printf("n = %d\n", n);

	return 0;
}

法2:用位操作符来实现

以3为例:

第一次

3:00000000000000000000000000000011

1:00000000000000000000000000000001

第二次

3>>1: 00000000000000000000000000000011

      1: 00000000000000000000000000000001

判断32位

3&1==1就说明从右至左第一位上是一,如果要判断第二位上是不是1,只需将3>>1,再次&即可,从而判断出3的二进制中有2个1.

简单的总结一下就是:用一个数&1,得到结果是1则这个数的二进制这一位上是1,然后将这个数>>再&1,一共判断32位

代码如下:

int count_num_of_1(unsigned int num)   
{
	int count = 0;
	int i = 0;

	for (i = 0; i < 32; i++)
	{
		if (((num >> i) & 1) == 1)
		{
			count++;
		}
	}

	return count;
}
#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);

	int n = count_num_of_1(num);

	printf("n = %d\n", n);

	return 0;
}

法3:先说一下法1和法2的缺点,判断次数过多,代码效率太低。下面介绍一种奇妙的方法

以15为例:

n&(n-1)
n=15
1111     n
1110     n-1
1110     n
1101     n-1
1100     n
1011     n-1
1000     n
0111     n-1
0000     结束

奇妙在于每一次n&(n-1)都会剥离下一个1

代码如下:

int count_num_of_1(int num)
{
	int count = 0;

	while(num)
	{
		num = num & (num - 1);
		count++;
	}

	return count;
}
#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);

	int n = count_num_of_1(num);

	printf("n = %d\n", n);

	return 0;
}

当然n&(n-1)还有其他的作用:

1 判断一个数是不是2的n次方:

2^1
10
2^2
100
2^3
1000

观察发现2的n次方的特点是二进制中只有一个1,直接n&(n-1),如果等于0则是2的n次方

代码如下:

#include<stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);

	if ((n & (n - 1)) == 0)
	{
		printf("是2的n次方\n");
	}

	return 0;
}

2 求两个数二进制中不同位的个数

常规思路就是上面法2,两个数>>后&1,后比较结果是否为1

奇妙的思路:现将两个数^,  ^后相同的为0,不同的为1,后直接计算^得到的这个数二进制中1的个数

代码如下:

int count_diff_bit(int m, int n)
{
	int count = 0;

	//异或操作符
	//相同为0,相异为1
	int ret = m ^ n;
	
	//统计一下ret中二进制位有几个1
	while (ret)
	{
		ret = ret & (ret - 1);
		count++;
	}

	return count;
}
#include<stdio.h>
int main()
{
	int m = 0;
	int n = 0;
	scanf("%d %d", &m, &n);
	int ret = count_diff_bit(m, n);
	printf("%d\n", ret);

	return 0;
}

后再接一个简单的小题,如何求一个数的二进制中的奇数序列和偶数序列。

思路如下:

最高的奇数位是第31位,现将这个数>>30去&1判断,后>>28,循环下去,每次>>数字减2且>=0

最高的偶数位是第32位,现将这个数>>31去&1判断,后>>29,循环下去,每次>>数字减2且>=1

代码如下:

#include<stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);

	int i = 0;

	//获取偶数位的数字
	printf("偶数序列:");
	for (i = 31; i>=1; i -= 2)
	{
		if (((n & (1 >> i)) == (1 >> i)))
		{
			printf("%d",((n>>i)&1));
		}	
	}

	printf("\n");

	//获取奇数位的数字
	printf("奇数序列:");
	for (i = 30; i >=0; i -= 2)
	{
		if (((n & (1 >> i)) == (1 >> i)))
		{
			printf("%d", ((n >> i) & 1));
		}
	}

	printf("\n");

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值