求二進位制數中1的個數

2021-07-08 09:37:10 字數 2055 閱讀 8544

題目描述

給定乙個整數,輸出該數二進位制表示中1的個數。其中負數用補碼表示。

方法一:直覺法。完全憑直覺。

int bitcount(unsigned int n)

return c ;

}

方法二:hamming weight

要介紹漢明重量,就要提到漢明距離。

在資訊理論中,兩個等長字串之間的漢明距離是兩個字串對應位置的不同字元的個數。

漢明重量是字串相對於同樣長度的零字串的漢明距離,也就是說,它是字串中非零的元素個數:對於二進位制字串來說,就是1的個數,所以11101的漢明重量是4。

求漢明重量的演算法有很多,經典的高效演算法是通過位運算來實現的。

舉例說明,本例子中的運算均為二進位制運算。

考慮2位二進位制整數 n=11,總共有2個1,讓奇數字與它相鄰的左邊的偶數字相加,也就是把n右移1位,然後與原來的n相加,因為每對兒奇偶位相加的和不會超過兩位,所以結果用乙個相鄰的兩位來儲存原數n中兩個相鄰一位中1的個數;

之後,重複上述思想,把從低位開始,相鄰的兩位看做乙個整體。用這個兩位與它左邊相鄰的兩位來做位加運算。

相應的如果n是四位整數 n=0111,先以「一位」為單位做奇偶位提取,然後偶數字移位(右移1位),相加;再以「兩位」為單位做奇偶提取,偶數字移位(這時就需要移2位),相加,因為此時沒對奇偶位的和不會超過「四位」,所以結果中儲存著n中1的個數,依次類推可以得出更多位n的演算法。整個思想類似分治法。

最後,還要再強調一點,進行右移的一定要是無符號數,對於無符號數,右移是邏輯右移,即高位是補0的。對於有符號數,右移是算術右移,高位是補符號位的。

下面是維基上面完全忠實於上述演算法的c**描述。

const uint64_t m1  = 0x5555555555555555; //binary: 0101...

const uint64_t m2 = 0x3333333333333333; //binary: 00110011..

const uint64_t m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones ...

const uint64_t m8 = 0x00ff00ff00ff00ff; //binary: 8 zeros, 8 ones ...

const uint64_t m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones ...

const uint64_t m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones

const uint64_t hff = 0xffffffffffffffff; //binary: all ones

const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...

int popcount_1(uint64_t x)

上述**對於理解上述演算法是非常有幫助的,但是對於機器執行來說,還是有結構性優化的空間。

方法三:這個演算法很巧妙,但是不經過別人指點,不太容易想到。

其運算次數與輸入n的大小無關,只與n中1的個數有關。如果n的二進位制表示中有k個1,那麼這個方法只需要迴圈k次即可。其原理是不斷清除n的二進位制表示中最右邊的1,同時累加計數器,直至n為0,**如下:

int bitcount2(unsigned int n)

return c ;

}

為什麼n &= (n – 1)能清除最右邊的1呢?因為從二進位制的角度講,n相當於在n - 1的最低位加上1。舉個例子,8(1000)= 7(0111)+ 1(0001),所以8 & 7 = (1000)&(0111)= 0(0000),清除了8最右邊的1(其實就是最高位的1,因為8的二進位制中只有乙個1)。再比如7(0111)= 6(0110)+ 1(0001),所以7 & 6 = (0111)&(0110)= 6(0110),清除了7的二進位制表示中最右邊的1(也就是最低位的1)。

求二進位制數中1的個數

解法一 可以舉乙個八位的二進位制例子來進行分析。對於二進位制操作,我們知道,除以乙個2,原來的數字將會減少乙個0。如果除的過程中有餘,那麼就表示當前位置有乙個1。以10 100 010為例 第一次除以2時,商為1 010 001,余為0。第二次除以2時,商為101 000,余為1。因此,可以考慮利用...

求二進位制數中1的個數

對於乙個位元組 8bit 的變數,求其二進位制表示中 1 的個數,要求演算法的執行效率盡可能地高。解法一 可以舉乙個八位的二進位制例子來進行分析。對於二進位制操作,我們知道,除以乙個2,原來的數字將會減少乙個0。如果除的過程中有餘,那麼就表示當前位置有乙個1。int count int v int ...

求二進位制數中1的個數

對於乙個位元組 8bit 的無符號整型變數,求其二進位制表示中 1 的個數。c codes as below using system class program static void main string args program program new program for int i 0...