//編寫代碼實現:求一個整數存儲在內存中的二進制中1的個數
//第一種寫法
/*int count_bit_one(unsigned int n)
{int count = 0;while (n )//除到最后余數是0,那么這個循環就結束了{//這個題就是可以想成求15的二進制的過程//每次都除以2,余數為1的時候就count++if ((n % 2) == 1)//假設輸入的是15count++;n = n / 2;//換下一個數繼續除,直到所有的數除完//15/2=7 7/2=3 3/2=1 1/2=0,四次計算,每次計算的余數都為1}//15的二進制是1111return count;
}
//對于這部分函數不理解的話可以自己畫出自己一次計算的一個數的二進制的過程int main()
{int num = 0;scanf("%d", &num);int ret = count_bit_one(num);printf("%d\n", ret);return 0;
}*/
但是我們輸入-1,這個輸出結果就有問題了
解決方法:傳過去num,我們用unsigned int n來接收傳過來的數,
使用 unsigned int 在這個函數中是恰當的,因為它確保了函數可以正確處理所有非負整數值,并且避免了有符號整數可能帶來的問題。//第二種算法--不考慮正負號
//-1在內存中的補碼是全1
//11111111111111111111111111111111
//不關心符號的寫法//n&1==1 就說明n的二進制位的最低位是1
//n&1==0 就說明n的二進制位的最低位是0//計算完這一位,想要計算下一位,那么就需要用到
//右移操作符了
//把n的二進制數的每一位都移到最低位
//00000000000000000000000000000001--1的補碼
//因為&的用法是對應的二進制位,
// 有0則為0,兩個同時為1才為1
//如果n的二進制數最低位和1的二進制數最低位產生反應,
//那么兩個1就會場生一個1,
// 如果n的最低位數字是0,那么產生的數字僅僅是0
/*int count_bit_one(int n)
{int count = 0;for (int i = 0; i < 32; i++){//有0則為0,兩個同時為1才為1if ((n >> i) & 1 == 1)//i是從0開始的,也就是最開始的n的最低位//然后利用右移操作符依次變更最低位的數字{count++;//如果結果為1那么就++} }return count;
}int main()
{ int num = 0; scanf("%d", &num); int ret = count_bit_one(num); printf("%d\n", ret); return 0;
} *///第三種寫法
//鋪墊
/*
n=11 n=n&(n-1)
二進制
一開始:
n = 1011
n-1= 1010
賦值后:
n=n&(n-1), &有 0就是0,兩個1就是1
得到一個新的n
n = 1010
n-1 =1001
再次用新得來的n和n-1來為新的n賦值
n=n&(n-1)
n = 1000
n-1 = 0111
再次賦值
n=n&(n-1)
n=0000n從最開始的1011不斷賦值到0000,
n=n&(n-1)這個方程把n的二進制序列中的最右邊的1去掉了
*///即通過反復應用 n = n & (n - 1); 直到 n 變為0,
// 每次操作清除一個1,計數器增加1,最后得到1的總數。int count_bit_one(int n)
{int count = 0;int i = 0;while (n)//循環停下來的時候n就變成0了{n = n & (n - 1);//執行一次就會去掉一個1count++;}return count;
}int main()
{int num = 0;scanf("%d", &num);int ret = count_bit_one(num);printf("%d\n", ret);return 0;
} 每次執行 n = n & (n - 1); 都會減少 n 的二進制表示中1的個數,直到沒有1剩下,此時 n 變為0,循環結束。