求一个数的二进制序列中1的个数(3种方法)

前言:一个数要存储在计算机中,是以该数二进制补码形式存储的。

法1(不推荐使用):

思路:当我们想要得到一个十进制数的每一位时,通常是采用模10除10的方法,模10得到最低位,除10得到高位,一直重复。那么想要得到一个数的二进制的每一位时,也可以采用模2除2的方法。


//求一个数存储在二进制数中1的个数(补码形式存储,所以算的是该数二进制补码中1的个数)

int count_one1(int m)   //不适用于负数
{
	int count = 0;
	while (m)   
	{
		if (m % 2 == 1)   //最低位是1
		{
			count++;
		}
		m /= 2;  //处理完最低位后将其丢掉
	}
	return count;
}
int main()
{
	int n = 1;
	int count = count_one1(n);
	printf("%d\n", count);
	system("pause");
	return 0;
}

但我们发现,一个负数不论%2还是/2结果永远是负数,所以用上述代码求解1的个数时永远都是0个,所以此种方法只适用于正数。

法二(推荐使用):

思路:我们知道一个数的二进制&1可得该数二进制最低位是0还是1,那么在此基础上,只要我们每次判断完最低位后右移一位就可以得到此时最低位的值,移31位便可得到该数二进制中1的个数。

int count_one2(int m)  //必须要循环32次,效率太低
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (((m >> i) & 1) == 1)
		{
			count++;
		}
	}
	return count;
}

int main()
{
	int n = -1;
	int count = count_one2(n);
	printf("%d\n", count);
	system("pause");
	return 0;
}

但是此种方法效率太低,如果一个数的二进制补码中1全部集中在低位,而高位无0,循环32次无疑拉低了程序的运行效率。

法3(推荐使用):

思路:我们发现一个数和该数减1后做按位与操作再赋给该数,即某数=某数&(某数-1),每执行一次,该数二进制最右边的1就会丢掉。那么我们便可以知道,只要一个数在变成0之前能执行多少次某数=某数&(某数-1)操作,该数的二进制便有多少个1。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <windows.h>
int count_one3(int m)
{
	int count = 0;
	while (m)
	{
		m = m&(m - 1);
		count++;
	}
	return count;
}
int main()
{
	int n = -1;
	int count = count_one3(n);
	printf("%d\n", count);
	system("pause");
	return 0;
}

此方法既适用于负数,又大大提高了程序执行的效率。

  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值