位運算(一):二進位制中1的個數

XHfight發表於2016-05-29



一、題目:求二進位制中1的個數
       請實現一個函式,輸入一個整數,輸出該數二進位制表示中1的個數。
       例如:10 二進位制表示為:1010 ,該函式輸出二

二、最初思路:
       先檢查二進位制位最右邊一位是否為1,將二進位制位右移一位,這時最右邊一位
變為原來的倒數第二位,再右移一位,依次迴圈運算,直到此數變為0。
       怎樣檢查二進位制位最右邊一位是否為1呢?用這個數&1,若結果為0,則是0,否則為1。

三、改進:
   1.輸入的數為負數,最高位為1,右移時最高位會填充1,用上述方法則會死迴圈。
     思路應修改為:先&1判斷最右邊一位是否為1,然後將1左移一位再&判斷右邊第二位
     是否為1,與運算的結果為0,則該位不是1,否則都為1。直到1左移為0結束迴圈.
   2.上述思路32位整數需要移動32次,改進為整數中有多少個1就迴圈多少次。
     思路應修改為:將一個整數減去1然後與這個整數做與運算,結果恰好將最右邊的1變為0
     例:最低位為1:(1001)&(1000)= 1000
            最低位為0:(1010)&(1001)= 1000

四、程式碼實現(編譯器:VS2010      語言: C語言)

#include <stdio.h>
#include <stdlib.h>

 

int NumberOfOne(int n)
{
 int count = 0;
 /*方法1:最初思路 未解決負數問題
 while(n)
 {
  if((n&1) == 1)
  {
   count++;
  }
  n>>=1;
 }*/
/*方法2:改進1  32位整數要迴圈32次
 unsigned int flag = 1;
 while(flag)
 {
  if(flag & n)
   count++;

  flag <<= 1;
 }*/


 //方法3:終極方法 優化了方法2,有多少1就迴圈多少次
 while(n)
 {

  n &= (n-1);
  count++;

 }
 
 return count;
}
int main()
{
 int num = -10;

//-10在記憶體中的儲存,求-10的補碼

//10000000 00000000 00000000 00001010  ->10
//11111111 11111111 11111111 11110101  ->取反
 //11111111 11111111 11111111 11110110  -〉+1
 int ret = NumberOfOne(num);
 printf("%d\n", ret);
 system("pause");
 return 0;
}


參考書籍《劍指offer》
謝謝閱讀,如有錯誤,歡迎指出,在此感謝!!!

相關文章