代码要求
输入一个整数n,输出该数32位二进制中为1的个数(包括最高位的符号位),其中负数用补码表示
如:输入:15 (15的二进制表示:0000 1111)
输出:4
代码实现
方法一:摸2除2
#include<stdio.h>
int number_of_one(int n)
{
//计数
int count = 0;
while (n)
{
if (n % 2 == 1)
count++;
n = n / 2;
}
return count;
}
int main()
{
//输入
int n = 0;
scanf("%d", &n);
//计算n的二进制中1的个数并返回
int ret = number_of_one(n);
//输出
printf("ret = %d\n", ret);
return 0;
}
代码讲解:
二进制:0001,转换为十进制:1
二进制:0011,转换为十进制:3
二进制:0111,转换为十进制:7
二进制:1111,转换为十进制:15
由此可见,从 1的二进制 到 15的二进制 中1的个数依次递增1,且从15到1有整数除二的效果
所以可以得出结论:一个正整数n在除2摸2后就能得到这个正整数n的每一位
代码验证:
代码缺点:
-1的补码是32个1,但是以上代码逻辑输入-1时只会输出1,题目中要求负数用补码表示,所以以上代码并不能完全实现返回整数的二进制中1的个数
代码补全方法:
将函数中的形参接收以无符号整型接收(unsigned int),最高位也会被看作有效位,就会将 -1 看作正整数,此时的 -1 的二进制就是 32个全一 的正整数
代码补全验证:
方法二:位移操作符
#include<stdio.h>
int number_of_one(int n)
{
//计数
int count = 0;
for (int i = 1; i <= 32; i++)
{
if (((n >> i) & 1) == 1)
count++;
}
return count;
}
int main()
{
//输入
int n = 0;
scanf("%d", &n);
//计算n的二进制中1的个数并返回
int ret = number_of_one(n);
//输出
printf("ret = %d\n", ret);
return 0;
}
代码解析:
解析:if (((n >> i) & 1) == 1)
变量i的范围是1~32,刚好 n >> i 就能遍历n的补码中的每一位,再按位与(&)上1,看是否全等于1,全等的话就说明 n >> i 的那一位补码刚好就是1
代码验证: