c语言经典小题:求一个整数存储在内存中的二进制中“1”的个数(三种方法求解)

本文介绍了三种计算存储在内存中二进制补码中1的个数的方法:倒基求余法、移位操作和算法n=n&(n-1)。特别指出,处理负数时需使用无符号整数避免错误。
摘要由CSDN通过智能技术生成

题目描述

分析:我们知道存储在内存的二进制为补码,所以我们求的是补码中“1”的个数。接下来我将会介绍三种方法进行求解。

方法一:倒基求余法

       为了更好理解,我们先在十进制中推演。在十进制中,以123为例,求123中“1”的个数,我们会怎么做?我们大概率会想到“%10再/10”这种方法,这样可以帮我们的到这个整数的最后一位,再去掉它的最后一位。

       联系到二进制中,我们我们不难想到用%2再/2的方法得到含“1”的每一位,这样再定义一个变量count统计“1”的个数,用for循环每次得到“1”的时候conut++就可以求出“1”的个数。接下来我们以13为例。

不难发现,当余数为1是,得到的二进制为也是1,余数为0时,得到的二进制位也是0。则可以根据这个规律写代码。

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	int count = 0;//计数
	while (num)
	{
		if (num % 2 == 1)
		{
			count++;
		}
		num /= 2;
	}
	printf("二进制中1的个数为:%d\n", count);
	return 0;
}

       如果你以为这样就万无一失的话,那你就大意了,请看:

      当我们输入-1时,得出的二进制中1的个数为0,事实上-1在内存中的二进制中的个数为32,所以得出的答案是错的。为什么呢?分析一下:当num==-1时,-1%2!=1,则count++不执行,而-1/2==0,while循环不执行,此时count依然为0,故得出的答案为零。可以得出,当输入num为负数时,这种方法是行不通的。有没有什么方法可以改进呢?有的。我们在定义num变量是不要定义有符号整数int num,定义无符号整数unsigned int num就可以规避这个问题了。定义无符号整数,这样不管输入的num是正还是负,都会把num当作无符号来看,它的最高位1或0也不会当做符号位来看。下面是改过之后的代码和运行后的截图:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
int main()
{
	unsigned int num = 0;
	scanf("%d", &num);
	int count = 0;//计数
	while (num)
	{
		if (num % 2 == 1)
		{
			count++;
		}
		num /= 2;
	}
	printf("二进制中1的个数为:%d\n", count);
	return 0;
}

 

方法二: 利用移位操作实现

      利用移位操作符(>>)对一个十进制数num进行移位操作,将最高位的数移至最低位,总共要移31位,移位后使用和1相与(&),这样可以将高位依次清零,由于1在内存中除最低位是1,其余31位都是零,把相与的数按十进制输出。用for循环做相同的操作,直到最后一位。如果相与为1,count++,则可以得到“1”的个数。再以13为例:

define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	int count=0;
	for (int i = 0; i < 32; i++)
	{
		if (((num >> i) & 1) == 1)//num向右移动0位实际上就是没有移动,求得就是最低位
		{
			count++;
		}
	}
	printf("%d\n", count);
	return 0;
}

方法三:算法n=n&(n-1)

      这个表达式能把n的二进制最右边的"1"去掉,最后将整数归零。整体思路是,每次将n与n-1相与的结果赋给n,n如果为1,则count++。接下来以15为例:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
int main()
{
    int num = 0;
	scanf("%d", &num);
	int count=0;
	while (num)
	{
		count++;
		num = num & (num - 1);
	}
	printf("%d\n", count);
	return 0;
}

 

       以上就是求一个整数存储在内存中的二进制中“1”的个数的三种方法。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值