日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hamming weight_popcount或者hamming weight(二进制1的个数问题)

發布時間:2025/3/21 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hamming weight_popcount或者hamming weight(二进制1的个数问题) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第一次寫關于算法的問題。今天數據庫課老師在講數據庫底層實現的時候提到了位圖索引,最后歸結為1的個數,以前看到很多次關于1的個數的計算,今天總結一下。

最開始是有《編程之美》里面的問題引出的:如何最快地讀取到二進制中1的個數.

最開始我也是感覺一個個地數不就完了,但是人家說了要求最快。一個個的數是O(N)級的。

1. 比如:int count=0;

for(;x;x>>1)

{

count++;

}//當然也有每次用x直接除以2 的。

2.后來就是用x&(x-1)的結果是否為0來判斷,如果為零,有一個1,否則沒有。

所以有:

for(;x;count++)

x&=x-1;

3.查表大法,就是一一列舉這n位二進制所有的可能到數組中,然后直接查表就是了,這里就不贅述了

4.這個新的方法叫shift and add,正如名字一樣,該算法用的就是shift 和add(移位和加法):

對于n位二進制數,最多有n個1,而n必定能由n位二進制數來表示,因此我們在求出某k位中1的個數后,可以將結果直接存儲在這k位中,不需要額外的空間。

以4位二進制數abcd為例,最終結果是a+b+c+d,循環的話需要4步加法

那么我們讓abcd相鄰的兩個數相加,也就是 a+b+c+d=[a+b]+[c+d]

[0 b 0 d]

[0 a 0 c]

--------

[e f] [ g h]

ef=a+b ? gh=c+d 而 0b0d=(abcd)&0101,0a0c=(abcd)>>1 &0101

[ef] ?[gh]再相鄰的兩組相加

[00 ef]

[gh]

--------

i j k l

ijkl=ef+gh ?gh=(efgh)&& 0011 ,ef=(efgh)>>2 & 0011

依次入次遞推。需要log(N)次

代碼如下:

typedef unsigned __int64 uint64; //assume this gives 64-bits

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

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

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

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

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

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

int popcount_1(uint64 x) {

x = (x & m1 ) + ((x >> 1) & m1 );

x = (x & m2 ) + ((x >> 2) & m2 );

x = (x & m4 ) + ((x >> 4) & m4 );

x = (x & m8 ) + ((x >> 8) & m8 );

x = (x & m16) + ((x >> 16) & m16);

x = (x & m32) + ((x >> 32) & m32);

return x;

}

5.對shift and add的優化:

看到有三種優化,這里只提兩種吧

1

int popcount_2(uint64 x)

{

x -= (x >> 1) & m1;

x = (x & m2) + ((x >> 2) & m2);

x = (x + (x >> 4)) & m4;

x += x >> 8;

x += x >> 16;

x += x >> 32;

return x & 0x7f;

}

2.

int popcount_3(uint64 x) {

x -= (x >> 1) & m1;

x = (x & m2) + ((x >> 2) & m2);

x = (x + (x >> 4)) & m4;

return (x * h01)>>56;

據說這可是MIT的牛人想出來的高招(當時是求余,現在換成除法了更快)

我也是參見了wikipedia(但是看不懂)和http://blog.ibread.net/375/pop-count-problem/上面的文章。

int popcount_3(uint64 x) {

x -= (x >> 1) & m1;

x = (x & m2) + ((x >> 2) & m2);

x = (x + (x >> 4)) & m4;

return (x * h01)>>56;

總結

以上是生活随笔為你收集整理的hamming weight_popcount或者hamming weight(二进制1的个数问题)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。