写一个函数返回参数二进制中 1 的个数。

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值