【c语言】三种方法统计二进制中1的个数

一、根据进制特性,得到二进制中每一位

如果想得到2进制中的每一位,不如先看看10进制中的每一位怎么得到

给出一个10进制的数,怎么得到每一位呢?

思路:

比如15

15%10=5(得到个位数) 15/10=1(去掉个位数)

再用1%10=1(再次得到个位数) 1/10=0(再次去掉个位数)

所以我只要它是个循环就好了,直到最后的结果为0——终止循环

注意上述计算是在c语言规定的所计算,15为int型变量,所以1/10=0

那么对于10进制的操作,对于2进制同样适用!

思路:

15为例

15%2=1(得到一个二进制位) 15/2=7(去掉刚得的二进制位)7%2=1(再次得到一个二进制位) 7/2=3(去掉刚得到的一个二进制位)3%2=1 3/2=1 1%2=1 1/2=0

15的二进制数为1111

故不断循环即可,终止等于0就不用继续了,条件就是结果==0——终止循环

也就是%2 /2,得到每个二进制位后再去除即可

但这种情况对于正数是满足的,但对于负数不适用

本质原因while循环的判断条件是判断该数是否为0

以-1为例,第一次-1能进入while循环,但在循环内计算-1/2=0,下次循环无法进入,但-1符号位的1没有计算到

那就让这个符号位不妨碍我们就好了,直接把这个负数转为unsigned int,这个负数变成无符号数后会成为一个很大的数,但并不妨碍我们求正数和负数中二进制中1的个数

代码如下:

#include<stdio.h>
int i(unsigned int n)//对于负数不适用,所以转为unsigned int
{
	int count = 0;
	while (n)
	{
		if (n % 2 == 1)
		{
			count++;//得到一个二进制位就++
		}
		n /= 2;//去除此二进制位
	}
	return count;
}
int main()
{
	int n;
	scanf("%d", &n);
	printf("%d", i(n));
	return 0;
}

2.利用移位操作符和位操作符

因为1的二进制只有最低位是1,所以再利用&操作符的特性,任何一个数与1&,都是这个数二进制位的最后一位&1的结果,所以我只要再利用>>操作符,让这个数的每个二进制位都和1&一遍,写个循环,我就可以知道1的个数了

#include<stdio.h>
int i(int n)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		//1是00000000 00000000 00000000 00000001
		//&后除了最低项其他项均为0
		if ((n >> i) & 1 == 1)//n>>i表示32位均有一次机会变成最低位
		{
			count++;
		}
	}
	return count;
}
int main()
{
	int n;
	scanf("%d", &n);
	printf("%d", i(n));
	return 0;
}

3.利用操作符执行几次就算出几个1

因为n与n-1 &几次,就会掉几个1(这个是可以验证的),所以只要看&几次就可以算出有几个1,直到n==0

#include<stdio.h>
int i(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;

	}
	return count;
}
int main()
{
	int n;
	scanf("%d", &n);
	printf("%d", i(n));
	return 0;
}
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值