可以先求一个数字十进位制中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)