二进制中1的个数(位运算)

题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

思路

①正数,很好解决该问题

②负数,如何呢?首先数据类型是int,4字节32位,负数统计的是补码中的1,可以先取反(取反操作是 在补码上进行的,且全部位都取反,负数都变成了正数,然后统计正数的1),再用互补原则32-sum,即可。

③其实不需要考虑怎么存储,从最低位开始与运算即可。int范围也就32位,移出界就变成0了,结束while。

代码

#include<stdio.h>
#include<string.h>
/**
正数:原码、反码、补码全部相等
负数:-5   (int 32位)
原码(10000000 00000000 00000000 00000101)
反码(11111111 11111111 11111111 11111010)最高位不反
补码(11111111 11111111 11111111 11111011)反码+1,-5在计算机中就是这样存储的
~操作,是在补码上操作的。
*****************************************************************************
负数:-1   (int 32位)
原码(10000000 00000000 00000000 00000001)
反码(11111111 11111111 11111111 11111110)最高位不反
补码(11111111 11111111 11111111 11111111)
****************************************************************************
负数:-2147483647   (int 32位)
原码(11111111 11111111 11111111 11111111)
反码(10000000 00000000 00000000 00000000)最高位不反
补码(10000000 00000000 00000000 00000001)
*****************************************************************************
负数:-2147483648   (int 32位)
原码(1..._10000000 00000000 00000000 00000000)  益界
反码(1..._01111111 11111111 11111111 11111111)  最高位不反
补码(1..._10000000 00000000 00000000 00000000)
*/
int  NumberOf1(int n){
    int sum=0;
    if(n<0){
        n=~n;
        while(n){
            if(n%2==1) sum++;
            n/=2;
        }
        return 32-sum;
    }else{
        while(n){
            if(n%2==1) sum++;
            n/=2;
        }
        return sum;
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    printf("%d\n",NumberOf1(n));
    return 0;
}
#include<stdio.h>
#include<string.h>
/**
不需要考虑正负数,负数也就是补码形式。
定义一个flag每次移位,进行与运算。
flag当移位出int范围就变为0。
...00000001
...00000010
...00000100
...00001000
...00010000
...
*/
int  NumberOf1(int n){
    int sum=0;
    int flag=1;
    while(flag){
        if(n&flag)
            sum++;
        flag=flag<<1;
    }
    return sum;
}
int main()
{
    int n;
    scanf("%d",&n);
    printf("%d\n",NumberOf1(n));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hqh131360239/article/details/80895088