1.方法一:
用十进制的方法思考,在十进制转二进制的过程中,我们要反复的将目标数字除以2,再对2取模,在对2取模的过程中,其实我们就得到了每一位二进制数(如下图所示),那么咱们一旦得到一位二进制数字,那我们就对其进行一次判断,如果是1,我们就设定一个计数器,并且加一,最后用这个计数器作为返回值,我们就得到了目标数字二进制中1的个数
代码实现及详解
函数numberof1中的参数之所以用unsigned int是因为这样可以避免负数的输入造成错误的结果,我们讲输入转化成没有符号的数字就可以得到正确的结果了。进入函数后我们使用while循环一直判断n对2取模是否为1(也就是二进制数是否为1),为1计数器就加1,最后n等于0,结束循环,返回计数器作为结果
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int numberof1(unsigned int n) { int count = 0; while (n) { if (n % 2 == 1) { count++; n /= 2; } } return count; } int main() { int n = 0; scanf("%d", &n); int ret = numberof1(n); printf("%d的二进制中1的个数为%d\n", n, ret); return 0; }
方法二:
首先我们知道,int型是4个字节,一个字节是8比特,也就是说一个整数在计算机中是以4*8=32位比特位来存储的,那我们只需要对这32位比特位依次遍历,不就得到了总共二进制的个数了吗。
代码实现及详解
我们使用一个for循环来循环32次,每一次循环我们都将目标数n右移i位,再与上1,我们知道0与1等于0,1与1等于1,1的二进制表示为00000000000000000000000000000001,也就是说任何数n与上1,都只能得到那个数的最后一位二进制数,知道了这些,我们就可以进行判断了,在判断了最后一位数是1后计数器就加1,然后依次遍历,最后得到结果
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int numberof1(int n) { int count = 0; for (int i = 0; i < 32; i++) { if (((n >> i) & 1) == 1) { count++; } } return count; } int main() { int n = 0; scanf("%d", &n); int ret = numberof1(n); printf("%d的二进制中1的个数为%d\n", n, ret); return 0; }
方法三:
这种方法比较难想,但是效率非常高,咱们举例说明,15的二进制表示为1111,15-1也就是14的二进制表示为1110,14-1也就是13的二进制表示为1101,以此类推,我们可以发现,任何数n和n-1的二进制之间只差了1位,而且这一位恰好就是0和1的区别,那么n与上(n-1)就可以消去一个1,也就是咱们每执行一次这样的操作,咱们就去掉了这个数二进制中的一个1,直到最后,这个数里面没有1了,那么数值也就变成了0,用计数器记录这个过程,最后就能得到我们想要的值
代码实现及详解
经过了我们上述的分析,我们就可以这样做,当最后n中的1消完了,n就等于了0,0表示假,while语句循环停止,最后返回计数器里面的值
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int numberof1(int n) { int count = 0; while (n) { n = n & (n - 1); count++; } return count; } int main() { int n = 0; scanf("%d", &n); int ret = numberof1(n); printf("%d的二进制中1的个数为%d\n", n, ret); return 0; }
程序运行结果图示
以上三种方法代码运行结果都是一样的,这里只是举例输出