題目描述 :
輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。
方法1:手動轉化法
直接想到的就是手動把數轉化爲二進制存進vector裏,然後去數1的個數。當然這個很麻煩的地方在於負數是用補碼,你把絕對值轉化成二進制之後還得變成補碼,工作量太多。
方法2:整數移位法
編程語言提供了位運算符,比如&(與)、|(或)、<<(左移)、>>(右移)等,位運算都是以二進制來操作的。
我們可以把這個整數不斷右移,每右移一次就判定一次末尾是不是1,一直右移到這個數變成0。判定末尾的方法是和1作相與操作,與之後是1則說明原數這一位是1。
代碼如下:
int count_one_way1(int num)
{
int counts=0;
while(num)
{
if((num&1)==1)
counts++;
num=num>>1;
}
return counts;
}
但是這段代碼有問題,問題在於右移補位的時候,正數補0,而負數補1,所以如果num是個負數,會陷入死循環。
方法3:1移位法
爲了避免上述問題,有一個改進方法是不移原來的數,我們把1這個數不斷左移,和原數的每一位作相與,然後每次想與的結果不是0,就說明原數這一位是1。
代碼如下:
int count_one_way2(int num)
{
int counts=0;
int t=1;
while(t!=0)
{
if((num&t)!=0)
counts++;
t=t<<1;
}
return counts;
}
這裏會t會一直左移,本機int有多少位,t就會移動多少位,也就是會和num的每一位都比較到。
方法4:相鄰數相與法
有一個很巧妙的方法是,n和n-1的相與結果,可以消掉n最右邊的1。比如說11-00&1011=1000。所以我們只需要不斷執行這種操作,就可以知道n有多少個1了。
代碼如下:
int count_one_way3(int num)
{
int counts=0;
while(num)
{
counts++;
num=num&(num-1);
}
return counts;
}
方法5:函數法
c++有頭文件提供了這個功能,這裏尖括號裏是32是因爲我的電腦的int型是32位。
#include<bitset>
int count_one_way4(int num)
{
return bitset<32>(num).count();
}