一个数字的二进制数字里的一的个数(负数用补码)

这篇博客探讨了两种在C语言中计算整数二进制表示中1的个数的方法。第一种方法存在死循环问题,无法正确处理-2147483648这个特殊的整数。第二种方法使用移位操作符,既快又准确。文章强调了处理二进制表示的边界条件和效率问题的重要性。
摘要由CSDN通过智能技术生成
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<math.h>
#include<stdlib.h>

这是预处理

int NumberOf1(int n)
{
 

    int i = 0, j, m, count = 0, x;
    x = n;
    if (n == -2147483648)//一个只有补码的负数
        return 1;

    while (1)
    {
        if ((n % ((int)pow(2, i))) == n )
        {
            break;
        }
            i++;
    }
    i--;
    for (j = i; j >= 0; j--)
    {
        m = n % ((int)pow(2, j));

        if (m != n)
            count++;
        n %= (int)pow(2, j);

    }
    if (x < 0 && x % 2 == 0)
    {
        count = 32 - count;
    }
    if (x < 0 && x % 2 != 0)
    {
        count = 33 - count;
    }
    return count;
}

这是一种解决问题的函数,缺点,会有死循环,((int)pow(-2, i))这个值的结果是整形永远达不到那个数字2147483648,我们必须自己规定那个数字

-2147483648这个数字是int的最小值没问题,确实可以等于

((int)pow(-2, i)))这个数字不可以达到-2147483648,因为是正数,所以超出范围了,数字变为1,达到这个数字必须是正数到2147483648加负号,但是没办法,正数是达不到的      

由于这个数字的特殊,我们得到10000000000000000000000000000000就是他的补码,即使我们用一些方法,比如说改变判断方式,设置整形不会超出范围,我们会得到这个二进制数(2147483648的无符号整形形态),导致他没有源码和反码,所以后面的公式对他无效。

反正就是很难受,int达不到2147483648,而这导致我们的任何运算结果(整形之间的计算,甚至加个负号,最后的结果都是整形)不能达到2147483648,这种方法的局限体现的淋漓尽致

导致我必须设立个别的入口
并且速度慢

int NumberOf2(int n)
{
    int i = 0, count = 0;
    for (i = 0; i < 32; i++)
    {
        if (n & (1 << i))   
//只要1移位后二进制1所在的位置对应到n那边有1这个表达式结果就不会为0,如00000000000000000100000000000000非0
//如果对应的那个数字是0,则表达式结果为
         count++;
    }
    return count;
}

法2:移位操作符<<    >>

左移,出界删掉,末位补0

右移动,有符号补符号位,无符号补0;

(-2147483648的补码就是10000000000000000000000000000000,很特殊)

(不过这个方法就是可以直接用补码来判定,并且速度快)

(正数三个码都一样)(而法一是一次一次慢慢的算出源码(-2147483648算到了符号位,顶替了hhh,导致后面的混乱),然后通过转化,但是很遗憾,-2147483648不能转化)

int main()
{
    int n = 0;
    scanf("%d", &n);
    system("cls");
    printf("%d\n", NumberOf1(n));
    printf("%d", NumberOf2(n));
    return 0;
}

这是原函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

s:103

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值