方法1: 辗转相除法
比如 :十进制数1234,想知道十进制中1的个数。
1234 --------num num%10==4 num=num/10;
123 --------num num%10==3 num=num/10;
12 --------num num%10==2 num=num/10;
1 --------num num%10==1 count++;
对应到二进制数中如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
int num;
int count = 0;
printf("Enter num:");
scanf("%d", &num);
while (num)
{
if (num % 2 == 1)
{
count++;
}
num = num / 2;
}
printf("count=%d\n", count);
system("pause");
return 0;
}
当num=0时,二进制数中没有1,所以直接输出count=0;
当num1=0时,执行循环;
但是: 该循环不能用于负数;比如当-1参与循环,-1%2!=1,count=0;
-1/10==0,不执行循环。输出count=0,但是实际上-1的二进制中有32个1;
方法2: 移位法
int main()
{
int num;
int i;
int count=0;
printf("Enter num:");
scanf("%d", &num);
for (i = 0; i < 32; i++)
{
if ((num & 1) == 1) //有0为0,全1为1;
{
count++;
}
num = num >> 1;
}
printf("count=%d\n", count);
system("pause");
return 0;
}
&:有0为0,全1为1;
所以num&1之后,最后一位若为1,num&1==1;否则num&1==0;
每次判断之后右移一位,一共判断32次。
但是: 循环32次,效率很慢。
方法3: 按位与法
int main()
{
int num;
int i;
int count=0;
printf("Enter num:");
scanf("%d", &num);
while (num)
{
num = num&(num - 1);
count++;
}
printf("count=%d\n", count);
system("pause");
return 0;
}
比如:000000000 000000000 00000000 00001111 --num
000000000 000000000 00000000 00001110 --num-1
000000000 000000000 00000000 00001110 --num num&(num-1)
000000000 000000000 00000000 00001101 --num-1
000000000 000000000 00000000 00001100 --num num&(num-1)
000000000 000000000 00000000 00001011 --num-1
000000000 000000000 00000000 00001000 --num num&(num-1)
000000000 000000000 00000000 00000111 --num-1
000000000 000000000 00000000 00000000 --num num&(num-1)
循环四次,输出4:;
当num=0 时循环结束,所以大大减少了循环的次数。