#define _CRT_SECURE_NO_WARNINGS 1
//写一个函数返回参数二进制中 1 的个数。
//比如: 15 的二进制是: 0000 1111 里面有: 4 个 1 。注意:算的是补码1的个数;
// 我们之前学过如果要得到一个整数的每一位的数,我们可以通过取模之后在取余的方式。
// 比如:
// 我们想得到整数:1234 的每一位的话;
// 我们可以: 1234 % 10 得到 —————— 4
// 再: 1234 / 10 得到 123
//
// 之后: 123 % 10 得到 —————— 3
// 再: 123 / 10 得到 12
//
// 之后: 12 % 10 得到 —————— 2
// 再: 12 / 10 得到 1
//
// 之后: 1 % 10 得到 —————— 1
// 再: 1 / 10 得到 0
// 通过以上方式我们得到了十进制的整数的每一位
// 这道题问我们二进制有多少个1,我们也要用类似的方法得到二进制数的每一位,在用一个if语句来判读该位是不是一就行了,
// 如果是1 则 计数器++;
// 十进制数我们是 % 10 和 / 10;
// 二进制数我们就 % 2 和 / 2 就可以了;
//#include<stdio.h>
//
//int shu_yi(int num)
//{
// int count = 0;
// while (num)
// {
// if (1 == num % 2)
// {
// count++;
// }
// num /= 2;
// }
// return count;
//
//}
//int main()
//{
// int num = 0;
// scanf("%d", &num);
// int ret = shu_yi(num);
// printf("%d\n", ret);
// return 0;
//}
// 但这种方法有一个漏洞:当你输入 -1 时 它的值并不是正确的结果;
// 所以我们试试方法2;
// 如果有一串二进制序列: 10100010101010000101010001000101
// 你想得到它的每一位可以咋办?
// 我们学了:按位与( & )
// 如果我们将这串二进制序列 按位与 1 (注意:& 的性质:有0就为0,全1才是1)
// 即:
// 10100010101010000101010001000101
// &
// 00000000000000000000000000000001
//得到 00000000000000000000000000000001 这串二进制就代表的 1;
//之后:再让原来那个二进制右移 1 位 得到:1010001010101000010101000100010 再 & 1 得到是 0;
//之后:再让原来那个二进制右移 2 位 得到:1010001010101000010101000100001 再 & 1 得到是 1;
//之后:再让原来那个二进制右移 3 位 得到:1010001010101000010101000100000 再 & 1 得到是 0;
//之后:再让原来那个二进制右移 4 位 得到:1010001010101000010101000100000 再 & 1 得到是 0;
// 发现规律:
// 我让原来那个二进制数 右移 i 位,如果移动之后的末尾是1,则 & 1 后得到 1;如果末尾是 0 则 & 1 后得到的是 0;
//#include<stdio.h>
//
//int shu_yi(int num)
//{
// int i = 0, count = 0;
// for (i = 0; i < 32; i++) // 32 是啥? 因为二进制位一共有32位。你每一位都要判断,所以要全部移动;
// {
// if (1 == ((num >> i) & 1))
// {
// count++;
// }
// }
// return count;
//
//}
//int main()
//{
// int num = 0;
// scanf("%d", &num);
// int ret = shu_yi(num);
// printf("%d\n", ret);
// return 0;
//}
// 其实我们还有个法子:
// 以前的程序员找出来了一个规律;
// n = n & (n-1) 这样的表达式只要运算一次; 只要运算一次,n 的二进制中最右边的一个1就会消失;】、
//举例:
// 假若我们有一个数:13
// 它的二进制序列: 1101 ———— n
// 那么: 1100 ———— n-1
// n & (n-1) 即 1101 & 1100 ————> 1100
// 看:n 的二进制(1101)中最右边的一个1就消失了;
// 再往下算一次:
// 1100 ———— n
// 那么: 1011———— n-1
// n & (n-1) 即 1100 & 1011 ————> 1000
// 看:n 的二进制(1100)中最右边的一个1就消失了,变成了:1000
// 所以我们可以算这个表达式执行了几次,因为执行一次少一个1,执行n次就少了n个1,我们就知道这个二进制序列有多少个1了;
#include<stdio.h>
int shu_yi(int num)
{
int count = 0;
while (num)
{
count++;
num = num & (num - 1);
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = shu_yi(num);
printf("%d\n", ret);
return 0;
}