0/1的奧祕:直接取二進制中1的個數的算法

【問題描述】:給一段位數爲n的二進制數,統計其中1的個數

【算法概述】:將二進制數按照每2位分組,計算每2位中1的個數,保存在一個二進制數中。然後迭代上述過程,就得到了每4位中1的個數,每8位中的1的個數,迭代下去,最終得到n位中1的個數

【算法複雜度】:log以2爲底的n

【算法描述】:摘自http://www.loveunix.net/html/200405/29967.html,作者: wingc  發佈日期: 2004-5-21

unsigned long CountBit(unsigned long X)

{

X = (X & 0x55555555) + (X >> 1 & 0x55555555);

X = (X & 0x33333333) + (X >> 2 & 0x33333333);

X = (X & 0x0F0F0F0F) + (X >> 4 & 0x0F0F0F0F);

X = (X & 0x00FF00FF) + (X >> 8 & 0x00FF00FF);

X = (X & 0x0000FFFF) + (X >> 16 & 0x0000FFFF);

return(X);

}
/*
0x55555555: 01010101010101010101010101010101
0x33333333: 00110011001100110011001100110011
0x0F0F0F0F: 00001111000011110000111100001111
0x00FF00FF: 00000000111111110000000011111111
0x0000FFFF: 00000000000000001111111111111111
*/

作者: wingc  發佈日期: 2004-5-22

哈哈,經指點,大概懂了,其實偶一直在想那個十進制數的變換過程應該有數學公式推導,導致偶一直在十進制數上打轉,要是把注意力仍停留在二進制數上,就不難理解了。(有可能真的有數學公式吧,但是與其找15->10->4的公式,不如直接觀察二進制串的變化過程更容易明白)

偶再拿一個長點的數(8位)說明一下,無雙大哥看看偶真的理解沒有

10101100(172)
| 第一次迭代(與01010101運算)
V
00000100 + 01010100 = 01011000

這一步將10101100每兩位上1的個數1(01)、1(01)、2(10)、0(00)計算出來了,但是這個值由於“權值”的問題,就是二進制數所在位數的問題,除了最後兩位00外前面三個都不能表達出真實意義,所以還需迭代

01011000
| 第二次迭代(與00110011運算)
V
00010000 + 00010010 = 00100010
這一步將10101100每四位數上1的個數2(0010)、2(0010)計算出來了,其實就是將上一步運算兩種顏色的值分別成對相加得到,同時,調整調整了“權值”,上一步中第一個01和第三個10的“權值”都下降兩位,這樣使後四位的0010的“權值”已經“正常”,可以表達實際2的意義了,但前四位仍在高位,還不能真實表達,仍需迭代

00100010
| 第三次迭代(與00001111運算)
V
0010 + 0010 = 0100(4)
這一步得到了1的個數的實際意義值,上一步第一個0010由於“權值”問題,還不能真實表達,而這一次,第一個0010“權值”下降四位,可以表達實際意義了,這樣加起來就是實際的1的個數了

總結,其實就是先算出每兩位1的個數的值,但是由於所在二進制位數的問題,導致了除最後兩位的值有真實的1的計數意義外,其他的都還不能真實表達,所以來第二次迭代,這次迭代計算出了每四位的1的個數,但是同樣的原因,出了最後四位值有真實的計數意義外,前四位仍然不能真實表達,再來第三次迭代,這次迭代算出了每八位的1的個數,也就是這個8位二進制數的1的個數啦~~
 

發佈了27 篇原創文章 · 獲贊 0 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章