一、hakmem演算法分析
1、整型數 i 的數值,實際上就是各位乘以權重——也就是乙個以2為底的多項式:
i = a0*2^0+a1*2^1+a2*2^2+...
因此,要求1的位數,實際上只要將各位消權:
a0+a1+a2+... 即係數和就是'1'的個數。
2、定理:對任何自然數n的n次冪,用n-1取模得數為1。
證明:若 n^(k-1) % (n-1) = 1 成立
則 n^k % (n-1) = ((n-1)*n^(k-1) + n^(k-1)) % (n-1) = 0 + n^(k-1) % (n-1) = 1 也成立
又有 n^(1-1) % (n-1) = 1
故對任意非負整數n, n^n %(n-1)=1
3、因此,對乙個係數為的以n為底的多項式p(n) = a0*n^n0+a1*n^n1+a2*n^n2+...
p(n)%(n-1) = (sum()) % (n-1) ;
如果能保證sum() < (n-1),則 p(n)%(n-1) = (sum())
也就是說,此時只要用n-1對多項式取模,就可以完成消權,得到係數和。
於是,問題轉化為,將以2為底的多項式轉化為以n為底的多項式,其中n要足夠大,使得n-1 > sum()恆成立。
32位整型數中ai=0或1,sum()<=32。n-1 > 32 ,n需要大於33。
因此取n=2^6=64>33作為新多項式的底。
4、將32位二進位制數的每6位作為乙個單位,看作以64為底的多項式:
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)
二、**
1、由上面分析可以得到**:
int bitcount(unsigned int n)
返回的就是1的個數。簡單吧
2、化簡一
上面是計算每六位中1的個數,得到上面原理分析的ti
但是,6位數中最多只有6個'1',也就是000110,只需要3位有效位,所以有些浪費
如果先得到每三位中1的個數,然後加一下也得到每六位1的個數,**如下:
int bitcount(unsigned int n)
這樣又減少了幾步!!
3、化簡二
如何計算三位中1的個數,如三位abc,1的個數無非是計算 a+b+c
乙個3位2進製數值是4a+2b+c
如果右移一位,變成2a+b;再右移一位,變成a
而(4a+2b+c) - (2a+b) - a = a+b+c 得到的就是我們想要的數
所以改**如下:
int bitcount(unsigned int n)
這樣又少了兩步,這才是最最簡單,複雜度最低的求1的個數的方法!!
**:
數32位 unsigned int中1的個數
參考文章 最簡單的方法 int bitcount0 unsigned int n return c 消除統計法 int bitcount2 unsigned int n return c 8bit查表法 unsigned int table 256 int bitcount2 unsigned in...
RK平台計算GPIO對應的整型數
gpio是比較常用的資源,比如說控制led燈亮滅,控制lcd上電,控制模組的復位電路,做外設的中斷腳等等,這些都有對gpio的操作和使用,所以說,gpio開發是驅動開發中必不可少的操作,而且也是最基礎的東西。我們在驅動開發過程中,有時候我們不能確定自己使用和申請的gpio是否對了,我們可以把它對應的...
計算機32位與64位的區別
叨叨32位和64位的區別,其實不嚴謹。32位 64位 指的可能是cpu,可能是作業系統,可能是安裝的軟體 多數情況說的計算機32位,64位指的就是cpu的區別,作業系統也屬於特殊的軟體吧 32 64位cpu的區別 1.控制匯流排能力不同 32位cpu只能控制32根匯流排 64位cpu可以控制64根匯...