求一个整数存储在内存中的二进制中1的个数(两种方法)

方法一:取余(%)相除(/)

1.1分析

首先,我们先创建一个变量count(用来统计二进制中1的个数),这时我们的想法就是拿到二进制的每一位。但我们该如何拿到二进制的每一位呢?

我们可以用类比的思想来解决这个问题,我们可以回想一下,我们在之前学过的逆序输出一个十进制数的每一位。同理我们也可以用相同的方法,来求二进制数的每一位,如果求得的结果是1,count++。

1.2代码实现

#include<stdio.h>
int main()
{
   int n = 0;
   scanf("%d", &n);
   int count = 0;//统计二进制中1的个数
   while(n)
   {
        if (n % 2 == 1)
        count++;
        n = n / 2;
   }
   printf("%d\n",count);
    return 0;
}

上面的代码其实是有问题的。因为当你去用-1这个数来检验的时候,你会发现结果是错误的。

1.21错误分析

整数的二进制的表示方式,有三种,分别是:原码、反码、补码。整数在内存中存储的是整数的补码。整数补码的求法:就是在原码的基础上取反加1。按照上面的方法,我们就可以求出-1的补码:11111111 11111111 11111111 11111111。所以,-1在内存中的二进制中1的个数,输出的结果应该是32。但当你用上面的代码将-1输入,输出的结果是0。(你要你输入的结果是负数,结果都是0)。说明:上面的代码对于负数是行不通的。行不通的本质是:对于while循环,当n=-1时,进入循环时,参与运算的是n的原码,而不是n的补码。对于正数而言,原码、反码、补码是相同的。当如果我们能然进入循环的是负数的补码,而不是原码,就可以解决问题了。

在这里插入图片描述

1.22修改

我们可以将n的类型改成unsigned int 类型就可以了。这里你可以自己先想一下。如果感觉不是很清晰,你可以参考一下我的理解,希望对你有帮助。

解析:unsigned int n = -1;对于这条语句我的理解是:向内存中申请4个字节的空间,来存放-1的补码,因为n的类型是unsigned int 所以对于-1的补码,其是没有符号位,全都是数值位,(这其实也就是为什么unsigned int 类型的数据比int类型的数据存储的东西多),原码、反码、补码是相同的。

在这里插入图片描述

通过我们n的类型的修改,我们就解决了问题。

方法二:利用位操作符

2.1分析

因为位操作符(&、|、^、~),它们对整数的补码来进行调整的。所以就想能不能通过位操作符来将二进制的每一位拿出来。

我们可以让整数的补码与1进行&如果结果等于1,那么就说明整数补码的最后一位是1,当你比较完以后,你要利用移位操作符,让补码的32位,每一位都进行比较。

使用&的原因:我们希望比较补码的“最后”一位时,补码中其他的1不产生影响。

2.2代码实现

#include<stdio.h>
int main()
{
    int n = 0;
    scanf("%d", &n);
    int count = 0;
    int i = 0;
    for(i = 0 ;i < 32; i++)
    {
        if((( n >> i) & 1) == 1)
            count++;
    }
    printf("%d\n",count);
    return 0;
}

希望这篇求整数存储在内存中二进制中1的个数能给大家带来帮助,欢迎读者留言讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值