题目描述
输入一个整数,输出该数二进制表示中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;
}