方法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 时循环结束,所以大大减少了循环的次数。