設x為二進位制數1111 1111 1111 1010,則求x中0的個數操作:
int countofzero(int x)
return n;
}
求x中1的個數操作:
int countofone(x)
return n;
}
(參考(侵刪):
演算法如下:
int bitcount(unsigned int n)
分析:
1. 整型數 i 的數值,實際上就是各位乘以權重——也就是乙個以2為底的多項式:
i = a0*2^0+a1*2^1+a2*2^2+... 因此,要求1的位數,實際上只要將各位消權:
i = a0+a1+a2+...所得的係數和就是'1'的個數。
2. 對任何自然數n的n次冪,用n-1取模得數為1。
3. 因此,對乙個係數為的以n為底的多項式p(n), p(n)%(n-1) = (sum()) % (n-1) 。
4. 將32位二進位制數的每6位作為乙個單位,看作以64(2^6)為底的多項式:
i = t0*64^0 + t1*64^1 + t2*64^2 + t3*64^3 + ...
各項的係數ti就是每6位2進製數的值。
這樣,只要通過運算,將各個單位中的6位數變為這6位中含有的'1'的個數,再用63取模,就可以得到所求的總的'1'的個數。
5. 取其中任意一項的6位數ti進行考慮,最簡單的方法顯然是對每次對1位進行mask然後相加,即
(ti>>5)&(000001) + (ti&>>4)(000001) + (ti>>3)&(000001) + (ti>>2)&(000001) + (ti>>1)&(000001) + ti&(000001)
int bitcount(unsigned int n)
第一步優化:
6位數中最多只有6個'1',也就是000110,只需要3位有效位。上面的式子實際上是以1位為單位提取出'1'的個數再相加求和求出6位中'1'的總個數的,所以用的是&(000001)。如果以3位為單位算出'1'的個數再進行相加的話,那麼就完全可以先加後mask。演算法如下:
tmp = (ti>>2)&(001001) + (ti>>1)&(001001) + ti&(001001)
(tmp + tmp>>3)&(000111)
int bitcount(unsigned int n)
注:**中是使用8進製數進行mask的,11位8進製數為33位2進製數,多出一位,因此第一位八進位制數會把最高位捨去(7->3)以免超出int長度。
從第乙個版本到第二個實際上是乙個「提取公因式」的過程。用1組+, >>, &運算代替了3組。並且已經提取了"最大公因式"。
第二步優化:
又減少了一組+, >>, &運算。被優化的是3位2進製數「組」內的計算。再回到多項式,乙個3位2進製數是4a+2b+c,我們想要求的是a
+b+c,n>>1的結果是2a+b,n>>2的結果是a。
於是: (4a+2b+c) - (2a+b) - (a) = a + b + c
中間的mask是為了遮蔽"組間""串擾",即遮蔽掉從左邊組的低位移動過來的數。
以上,這個演算法分析我還沒有看得太懂,先標記一下,下次再看~~~
求二進位制中1的個數
在 程式設計之美 一書中有一節提到如何求乙個位元組的無符號整型變數二進位制表示中中1的個數,主要提到了四種方法。下面簡單介紹一下 1.求餘法 在將十進位制數轉換為二進位制數時,採用除2取餘法。將每次除2得到的餘數儲存起來逆序輸出便是該十進位制整數的二進位制表示。因此可以採用這種方法去統計1的個數。i...
求二進位制中1的個數
解法有很多種 以乙個位元組無符號位元組變數作為例子 解法一 求餘法 在將十進位制數轉換為二進位制數時,採用除2取餘法。將每次除2得到的餘數儲存起來逆序輸出便是該十進位制整數的二進位制表示。因此可以採用這種方法去統計1的個數。public int count byte n return sum 解法二...
求二進位制中1的個數
這是乙個經常會在筆試和面試中遇到的題目,今天我做到了這個題目,就來分享一下我對這個題目的解決思路。首先拿到這個題目,我們的基本思路是 先判斷最後一位是否為1,接著把數字依次右移,判斷每一位是否為1,直到整數變為0為止。基於這個思路我們可以寫下如下的 int count int n n n 1 ret...