求二進位制數中1的個數

2022-02-17 09:10:34 字數 3094 閱讀 5423

任意給定乙個32位無符號整數n,求n的二進位制表示中1的個數,比如n = 5(0101)時,返回2,n = 15(1111)時,返回4。

使用移位操作,判末位是否為1;移位的次數為32。

int bitcount(unsigned int

n)

return

c ;}

這個方法我最喜歡,也常用。迭代n=n&(n-1),消除最右邊的1,計數。

int bitcount2(unsigned int

n)

return

c ;}

使用查表法。製作包含8bit所有整數對應1的個數的表,然後匹配32位n,匹配4次。

int bitcount3(unsigned int

n) ;

//初始化表

for (int i =0; i <256; i++)

unsigned

int c =0

;

//查表

unsigned char* p = (unsigned char*) &n ;

c = bitssettable256[p[0]] +bitssettable256[p[

1]] +bitssettable256[p[

2]] +bitssettable256[p[

3]];

return

c ;

}

所謂靜態表,就是把動態表的製作結果直接放到**中去。在資料量小的情況下,一般都會這麼做。

int bitcount4(unsigned int

n) ;

unsigned

int count =0

;

while

(n)

return

count ;

}

int bitcount7(unsigned int

n);

return table[n &0xff] +table[(n >>8) &0xff] +table[(n >>16) &0xff] +table[(n >>24) &0xff

] ;}

說實在的,這個我腦子一時轉不過來,不過**看起來很優雅。

int bitcount4(unsigned int

n)

先宣告,這是原作者起的名字,我不贊同。**裡有取模運算,而取模這種操作,我能不用的時候堅決不用,效能很差。我也沒看懂,下面會貼上網友的注釋。(可能我真的是老了,工作上安逸久了,是壞事。)

int bitcount5(unsigned int

n)

網友的解釋:

第一行**的作用

先說明一點,以0開頭的是8進製數,以0x開頭的是十六進製制數,上面**中使用了三個8進製數。

將n的二進位制表示寫出來,然後每3bit分成一組,求出每一組中1的個數,再表示成二進位制的形式。比如n = 50,其二進位制表示為110010,分組後是110和010,這兩組中1的個數本別是2和3。2對應010,3對應011,所以第一行**結束後,tmp = 010011,具體是怎麼實現的呢?由於每組3bit,所以這3bit對應的十進位制數都能表示為2^2 * a + 2^1 * b + c的形式,也就是4a + 2b + c的形式,這裡a,b,c的值為0或1,如果為0表示對應的二進位制位上是0,如果為1表示對應的二進位制位上是1,所以a + b + c的值也就是4a + 2b + c的二進位制數中1的個數了。舉個例子,十進位制數6(0110)= 4 * 1 + 2 * 1 + 0,這裡a = 1, b = 1, c = 0, a + b + c = 2,所以6的二進位制表示中有兩個1。現在的問題是,如何得到a + b +c呢?注意位運算中,右移一位相當於除2,就利用這個性質!

4a + 2b + c 右移一位等於2a +b

4a + 2b +c 右移量位等於a

然後做減法

4a + 2b + c –(2a + b) – a = a + b +c,這就是第一行**所作的事,明白了吧。

第二行**的作用

在第一行的基礎上,將tmp中相鄰的兩組中1的個數累加,由於累加到過程中有些組被重複加了一次,所以要捨棄這些多加的部分,這就是&030707070707的作用,又由於最終結果可能大於63,所以要取模。

需要注意的是,經過第一行**後,從右側起,每相鄰的3bit只有四種可能,即000,

001, 010, 011,為啥呢?因為每3bit中1的個數最多為3。所以下面的加法中不存在進製的問題,因為3 + 3 = 6

,不足8,不會產生進製。

tmp + (tmp >> 3)-這句就是是相鄰組相加,注意會產生重複相加的部分,比如tmp = 659 = 001

010010 011時,tmp >> 3 = 000

001010

010,相加得

001010

010011

000001

010010

---------------------

001011

100101

011 + 101 = 3 + 5 = 8

。注意,659只是個中間變數,這個結果不代表659這個數的二進位制形式中有8個1。

注意我們想要的只是第二組和最後一組(綠色部分),而第一組和第三組(紅色部分)屬於重複相加的部分,要消除掉,這就是&030707070707所完成的任務(每隔三位刪除三位),最後為什麼還要%63呢?因為上面相當於每次計算相連的6bit中1的個數,最多是111111 = 77(八進位制)= 63(十進位制),所以最後要對63取模。

我沒測,不過,不看好位域的效率。

struct

_byte

; long get_bit_count( unsigned char

b )

使用微軟提供的指令,首先要確保你的cpu支援sse4指令,用everest和cpu-z可以檢視是否支援。

unsigned int n =127

;unsigned

int bitcount = _mm_popcnt_u32(n) ;

求二進位制數中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...