首先要知道:
数据在打印时是原码,在内存中存放的是补码。
- 方法一(%2、/2):
以10为例:
补码:1010(有2个1)
10%2=0; 10/2=5
5%2=1; 5/2=2
2%2=0; 2/2=1
1%2=1; 1/2=0
(这里%2后的值即为其二进制数,每当n%2=1,count++,即1的个数加一
循环%2,当n=n/2=0时循环结束)
//方法一
int main()
{
unsigned int n = 0;//不能求负数,要加一个unsigned
int count = 0;//计算1的个数
scanf("%d", &n);
while (n)
{
if (n % 2 == 1)
{
count++;
n /= 2;
}
}
printf("二进制中1的个数为%d",count);
return 0;
}
- 方法二(移位操作符):
以13为例:
00000000 00000000 00000000 00001101 (13补码)
00000000 00000000 00000000 00000001 (1补码)
按位与(&)
00000000 00000000 00000000 00000001
若按位与之后的结果为1,则13的二进制的最后一位是1,进行count++
然后将13>>1,变为
00000000 00000000 00000000 00000110
00000000 00000000 00000000 00000001
按位与之后结果为0,最后一位不是1,不进行count++.
因为一共有32位,所以要循环32次进行判断
//方法二
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int count = 0;
for (int i = 0; i < 32; i++)//i为循环次数,循环32次
{
if ((n >> i) & 1 == 1)
count++;
}
printf("二进制中1的个数为%d",count);
return 0;
}
- 方法三(n=n&(n-1)算法):
以13为例:补码为1101
n: 1101 n: 1100 n: 1000
n-1:1100 n-1: 1011 n-1: 0111
n&(n-1): 1100 n&(n-1): 1000 n&(n-1): 0000
每进行一次n&(n-1)后,n就少一个1,直到n=0时,循环结束
//方法三
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
printf("二进制中1的个数为%d", count);
return 0;
}
注:因为方法二、三,是针对二进制来找1,所以正负不影响其求1的个数
而方法一,若定义时不加unsigned,只能用来求正数的二进制中1的个数