Problem Description:
Hz遇到一個數學問題,想請教聰明的你:給定一個有符号整數類型的數,Hz想知道該數
二進制表示中1的個數。其中負數用補碼表示。
Input:
測試樣例輸入包含一個有符号整數類型的整數n,注意可以是負數。
Output:
該數二進制表示中1的個數。其中負數用補碼表示。
Sample Input:
1
-5
Sample Output:
1
31
Prompt:
int占用4位元組,32比特(即32位),資料範圍為-2147483648~2147483647[-2^31~2^31-1]
負整數的補碼求法:将其對應正數二進制表示所有位取反(包括符号位,0變1,1變0)後加1
如 -5 其二進制補碼1的個數為31
-5對應正數5(00000000000000000000000000000101)
→所有位取反(11111111111111111111111111111010)
→加1 (11111111111111111111111111111011)
思路:這道題首先要知道十進制數轉化為二進制數的方法,然後要分正數和負數2種情況,正數比較簡單,就不說了,主要看負數的情況。負數的話,先把其對應的正數的二進制求出來,然後逐位取反,最後再将末尾數+1,其實這跟我們計算補碼的步驟一樣,隻不過現在要用計算機語言計算補碼,下面我們就看一下具體操作。
My DaiMa:
#include<stdio.h>
#include<iostream>
#include<math.h>
using
namespace
std;
int
main()
{
int
n,i,j,s,a[35];
while
(~
scanf
(
"%d"
,&n))
{
s=0;
if
(n>=0) //這是正數的情況
{
while
(n)
{
if
(n%2==1)
s++;
n/=2;
}
}
else
//負數的case
{
i=0;
n=
fabs
(n);//首先求對應正數的二進制
while
(n)
{
a[i]=n%2;
n/=2;
i++;
}
s=32-i;
for
(j=0;j<i;j++)//接下來就開始逐位取反
{
if
(a[j]==1)//1要變成0
a[j]=0;
else //0要變成1
a[j]=1;
}
a[0]=a[0]+1;//最後一步末尾加1,最後一步時最關鍵的一步,成功與否就看它的了
for
(j=0;j<i;j++)
{
a[j+1]=a[j+1]+a[j]/2;//主要原理是逢2進1;
a[j]=a[j]%2;
}
for
(j=0;j<i;j++)
{
if
(a[j]==1)
s++;
}
}
printf
(
"%d\n"
,s);
}
return
0;
}