求一个整数在内存中二进制中1的个数方法

一:和十进制除法类似:只适用于正整数。负数(可以转为无符号类型计算)

参考我们之前要取下十进制数字上的一位用的是取模10和除10,由于十进制转换为二进制就是用除2取余法,所以我们只要判断取出的余数是一还是零即可,但是这种方法不适用与负数,我认为是因为除2取余法背后的数学原理,还有负数在内存中的存储为补码有关,所以我们可以将a转为无符号类型,这样存储的负数补码就可以用除2取余数法了。

    unsigned int a =0;
	int count = 0;
	int i = 0;
    scanf("%d",&a);
	while(a)//若a为零,则无需再取余数
	{
		if (a % 2)//若取出余数为零,不进入if,若为1,进入if
		{
			count++;
		}
		a /= 2;
	}
	printf("%d", count);

对于在验证编译器是如何处理-1/2的我还有些疑问,比如我用二进制除法演算的时候,结果的这个二进制位应该如何存储,显示,读者老爷如果有兴趣,可以私信讨论讨论。

二:拿1与检验数字n按位与

   1 .拿这个数字n与1按位与(&),并移动数字1的二进制位

 按位与规则:两个操作数的二进制位上均为1才为1,只要有一个操作数上的二进制位上为零,则该位结果为零。

int a = 1;
	int n = 0;
	int count = 0;
	scanf("%d", &n);//输入要求二进制位1个数的数字
	while (a)
	{
		if (n&a)//我们在这里用按位与操作符,如果n在a上唯一的1的二进制位上也为1,结果必定不为零,if进入,count++
			count++;
		a <<= 1;//if不控制此处的语句,因为不管n在对应位上是否为1,我们都要往下一位检验
                //左移操作符左边抛弃,右边补零
	}
	printf("n二进制中1的有%d个", count);

(2)1与检验数字n按位与,右移动n

在用按位与操作符统计一个数上二进制位1的个数时,还可以不移动数字1,而移动要检验的n,我们此时可以用右移操作符把n上要检验

 在编译器中右移操作符默认左边补符号位,右边抛弃,对于一个数在32位机器下我们只需要判断三十二次,当然移动n的这个方法也可以复用第一种方法代码,但是负数会因为左边一直补1而陷入死循环。

    int a= 1;
	int n = 0;
	int count = 0;//计算retu二进制中1的个数
	scanf("%d", &n);
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if ((count >> i) & 1)
			count++;
	}

	printf("%d", count);

三 n与n-1按位与

例如1100与1011按位与,后结果为1000,1000与0111按位与为0,这说明数字n有多少个1就可以与进行多少次的n与n-1的运算

int c = 0;
	int y = 0;
	int sum = 0;
	scanf_s("%d", &y);
	while (y)
	{
		if (y - 1!=-1)
			sum++;//加不加if都可,因为y!=0,那y至少大于1
		y = y & y- 1;
	}
	printf("n二进制中1的有%d个", sum);

每次写博客的对我来说都是痛并快乐着,痛是有时候困顿在一些点上感觉自己描述不清楚,快乐是最后总算勉强能写完分享给大家,谢谢大家支持。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小何只露尖尖角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值