c语言求一个数字二进位制中一的个数

可以先求一个数字十进位制中1的个数

int main()
{
	int a = 0;
	printf("请输入要检验的数字");
	scanf("%d", &a);
	int count = count_bit_one(a);
	printf("count=%d\n", count);
	return 0;
}

main函数的解释说明:首先输入一个参数a并初始化 用printf打印函数打印提示语句

scanf进行识别扫描:这里的scanf的意思是扫描我们键盘输入的内容,%d表示输入的是整形

&a表示我们把输入的整形放在a的地址里去。

count_bit_one是我们构建的函数,我们把a当作函数的参数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int count_bit_one(int a)
{
	int count = 0;
	while (a)
	{
		if (a % 10 == 1)
		{
			count++;
		}
		a = a / 10;
	}
	return count;
}

接下来来构造函数部分,我们构造这个函数的目的是找出数字中1的个数,所以这个函数的返回值应该是整数,所以用int类型表示这个函数

(int a)这里的a可以替换成非a的其他数值,因为这里的a只是形式参数,只是用来接收函数声明传过来的参数。

首先,构建函数架构 :要求出数字的1出现的次数 可以从末尾到首位进行分析 假设我们输入的参数值为1211,我们可以通过求余数的方式来求这个数字的末位 ,%x表示这个数值对x的余数,例如1211%10=1 ,202%10=2。由此看见,求一个十进位制数的末位可以通过%10来求

既然我们求出了一个数的末位,例如我们求出了1211的末尾为1 ,我们下一步应该去掉末位,例121 我们再对121%10可以判断出121的末位,如此循环往复数,即可构建函数  。如何去掉末尾,可以让1211/10来得121  

这个循环可以用while(a)构建,  while(a)循环的意思是通过判断a的值,来决定while()循环是否继续执行下去 ,当a为非0值时 ,while()始终循环,当a为0时 ,while()循环终止,跳出这个循环。

通过上述函数可以求出十进位制中1的个数

请输入要检验的数字1121
count=3
请按任意键继续. . .

经过检测 代码正确

2 那接下来可以回归主题:求数二进位制中1的个数

把%10 /10 换为%2 /2,即可

while (a)
	{
		if (a % 2 == 1)
		{
			count++;
		}
		a = a / 2;
	}

进行试验  假设输入的值为11,11的二进位制序列为00000000000000000000000000001011,所以检测结果应该为3

请输入要检验的数字11
count=3
请按任意键继续. . .

经检验 ,代码正确。

但这种方法也有弊端,就是如何求负数的二进位制中1的个数,假设我们输入-1,来看看检测结果

请输入要检验的数字-1
count=0
请按任意键继续. . .

-1的二进位制在内存中存储的应该是补码,-1的源码是10000000000000000000000000000001。首位的1表示符号:0为正,1为负。整数的源码反码补码都相等,负数的反码=源码除首位(符号位),其余位数按位取反得到。负数的补码等于反码+1。所以-1的反码=11111111111111111111111111111110.-1的补码=11111111111111111111111111111111。由此可知,我们要得出的-1的二进位制中1的个数应该为32.

这种方法能不能改进呢?可以的,我们在函数中接受参数的类型用unsigned int来修饰,unsigned int表示我们接受的参数是无符号数,无符号数的话-1就等价于11111111111111111111111111111111二进位制下的数

int count_bit_one(unsigned int a)
{

经过检验

请输入要检验的数字-1
count=32
请按任意键继续. . .

实验成功

有没有其他的方法呢?还是有的,我们需要了解&操作符,&的意思按位与的意思,例如-1&1,-1的二进位制表示(补码)=11111111111111111111111111111111.  那1的二进位制表示则为:                                                      =0000000000000000000000000001  按位与得出的结果为                                                              =0000000000000000000000000001.  按位与的意思是二进位制表示中,如果对应位数都为1,则按位与得出的相同位数也为1,否则则为0.

了解了&,我们还要了解>>操作符,它的意思是将数字的二进位制向右移动,高位的补原符号位,低位的舍弃 。<<操作符和右移的类似,不同的是左移的高位舍弃,低位补零。

我们的思路是让我们输出的二进位制数&1,因为1的前31位都为0,所以a&1的前31位都为0(与a的值无关)。但1的第32位为1,当a的第32位也为1时,a&1=1,由此我们可以来构建函数

int count_bit_one(int a)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if ((a >> i) & 1 == 1)
		{
			count++;
		}
	}
	return count;
}

   这里的a>>i表示我们向右移的位数,i最大为32,表示最多向右移动32位,从而达到检测a二进位制中所有1的个数。

请输入要检验的数字-1
count=32
请按任意键继续. . .

进行试验,结果满足条件。         

接下来,我们来想是否有更好的办法:我们可以参考上面&的方法,进行改进                                         假设我们输出的数字为11  。11的二进位制表示形式为1011(前面的28位0省略)                                                                                  11-1的二进位制表示为1010     我们对这两个数字进行按位与操作                                                                          结果为   1010     接下来执行相同的方法                                                                                                       &1001                                                                                                                                                 =1000      继续执行                                                                                                                            & 0111                                                                                                                                                 =0       由此可知,每次执行一此循环,输出数字的二进位制排列的最末位都会消失,由此,我们可以通过判断循环的执行次数来判断二进位制序列中1的个数,这个循环可以用while循环来操作

int count_bit_one(int a)
{
	int count = 0;
	while (a)
	{
		a = a&(a - 1);
		count++;
	}
	return count;
}

我们输入-1,来检验代码是否有问题

请输入要检验的数字-1
count=32
请按任意键继续. . .

代码正确。

总结:求一个数的二进位制序列中有多少个1的方法有很多 1:通过取余数 取除数来逐位寻1            2:通过1和&操作符和>>操作符以及for循环来逐位寻1.  3:通过&操作符与a-1来进行最简便的求值(while)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值