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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

种群计数 (pop_count)

發布時間:2025/3/21 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 种群计数 (pop_count) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

//高效程序的奧秘hacker's delight Henry S. Warren, Jr. 著馮速譯

//5 章位計數5.1 1 位計數

// 應用:

//???? Hamming 距離是矢量間取不同值的對應位的數目,dist(x, y) = pop(x ^ y);

//?? 稀疏數組A 壓縮后的簡便訪問方式,可以利用位串數組BITS 記錄相應下標有定義的元素,

// 如每個有定義的A[i]BITS 的第I 個元素是1 位。

?

#include "iostream"

#include "bitset"

#include "limits"

#include "time.h"

?

using namespace std;

?

#define out2(T) cout<<bitset<numeric_limits<unsigned int>::digits>(T)<<endl;

#define SIZE(T) (numeric_limits<unsigned T>::digits)

?

bool SHR31(int x)?????????? //邏輯右移位

{

???? return (unsigned int)x>>31;

}

?

#define HOUT(x,y,z)??? hex_out(x,y,z)

?

inline void hex(int x)

{

???? int w = cout.width();

???? cout << "0x";

???? cout.width(8); cout.fill('0');

???? cout << hex << x << "? ";

???? cout.width(w);

}

inline void hex(unsigned __int64 x)

{

???? int w = cout.width();

???? cout << "0x";

???? cout.width(16); cout.fill('0');

???? printf("%I64x?? ",x);

???? cout.width(w);

}

void hex_out(int x, int y, int z)

{

???? hex(x); hex(y); hex(z); cout << endl;

}

?

// 循環左移位

int rotate(unsigned int x, int n)

{

???? return ? (x<<n) | (x >> (32-n));

}

?

// 統計x 中位1 的個數

// 首先設置每個2 位字段為原來的兩個單位的和,然后,求相鄰位字段的和,把結果放入相應的位字段,以此類推。

int pop(unsigned int 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;

}

?

// x 的第一個賦值基于下面這個相當巧妙的公式的前兩項

// pop(x) = x - floor(x/2) - floor(x/4) - ... - floor(x/2^31);

// 設字是b3b2b1b0

// bi = floor(x/2^i) - 2*floor(x/2^(i+1))

int pop2(unsigned int x)

{

???? x = x - ((x >> 1) & 0x55555555);

???? x = (x & 0x33333333) + ((x >> 2) & 0x33333333);

???? x = (x + (x >> 4)) & 0x0F0F0F0F;

???? x = x + (x >> 8);

???? x = x + (x >>16);

???? return x & 0x00000003F;

}

?

// [HAK, item169]

// http://www.inwap.com/pdp10/hbaker/hakmem/hacks.html

// DEC PDP-10計算機上只需要10 個指令

// 它是十進制計數的計算機,mod 63 很方便

// 注意:以0 開頭的數是八進制數

// 前三項萃取位字段的數目

// 舉例:如每三位字段全 111B

// (1): 取出高二位對應1 的值, 有兩個1 ,則取出后n 011

// (3): 取出最高位對應1 的值,有一個1 ,則取出后n 001

// (2),(4): x - n - n , 剛好11X - 011 - 001 2+X =高二位1 的數目+X

// 而最低位X 1 則自然加1,為0 自然加0

// (5): 合并相鄰的兩個三位字段成六位字段

// (6): mod 63 是怎么操作的呢?

// 假設六位字段值為a6 a5 a4 a3 a2 a1 a0

// 十進制和為a6*64^5 + a5*64^4 + ... + a0

// = a6* (63+1)^5 + a5* (63+1)^4 + ... + a0

// mod 63 剛好剩下a6 + a5 + ... + a0

// 從而把所有六位字段相加,統計1 的總和

int pop3(unsigned int x)

{

#define modu(x, y) (x % 63)

???? unsigned int n;

???? n = (x >> 1) & 033333333333;

???? x = x - n;

???? n = (n >> 1) & 033333333333;

???? x = x - n;

???? x = (x + (x >> 3)) & 030707070707;

???? x = modu(x, 63);

???? return x;

}

?

int pop4(unsigned int x)

{

???? unsigned int n;

?

???? n = (x >> 1) & 0x77777777;

???? x = x - n;

???? n = (n >> 1) & 0x77777777;

???? x = x - n;

???? n = (n >> 1) & 0x77777777;

???? x = x - n;

???? x = (x + (x >> 4)) & 0x0F0F0F0F;

???? x = x * 0x01010101;

???? return x >> 24;

}

?

int pop5(unsigned int x)

{

???? int n;

?

???? n = 0;

???? while (x != 0) {

???????? n += 1;

???????? x = x & (x - 1); // 把最右側的1 位改成0

???? }

???? return n;

}

?

int pop6(unsigned int x) {

???? int i, sum;

?

???? sum = x;

???? for (i = 1; i <= 31; i++) {

???????? x = rotate(x, 1);

???????? sum += x;

???? }

???? return -sum;

}

?

?

// 只計算七位量

int pop7(unsigned int x) {

???? x = x * 0x02040810;

???? x = x & 0x11111111;

???? x = x * 0x11111111;

???? x = x >> 28;

???? return x;

}

?

// 只計算八位量

int pop8(unsigned int x) {

???? x = x * 0x08040201;

???? x = x >> 3;

???? x = x & 0x11111111;

???? x = x * 0x11111111;

???? x = x >> 28;

???? return x;

}

?

int pop9(unsigned int x) {

???? int sum;

?

???? sum = x;

???? while (x != 0) {

???????? x = x >> 1;

???????? sum = sum - x;

???? }

???? return sum;

}

?

// table 存放0 255 x 的所有pop(x)

int pop10(unsigned int x) {

???? static char table[256] = {

???????? 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,

???????? 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,

???????? 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,

???????? 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,??

???????? 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,

???????? 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,?

???????? 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,?

???????? 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8

???? };

????

???? return table[x???????? ? & 0xFF] +

???????? ?? table[(x >> 8) & 0xFF] +

???????? ?? table[(x >>16) & 0xFF] +

???????? ?? table[(x >>24)];

}

?

//GNU c 的無符號long long

/*

int pop64(unsigned int x) {

???? unsigned long long y;

???? y = x * 0x0002000400080010ULL;

???? y = y & 0x1111111111111111ULL;

???? y = y * 0x1111111111111111ULL;

???? y = y >> 60;

???? return y;

}

*/

?

// 15 位量算術版本

const unsigned __int64 a = 0x0002000400080010;

const unsigned __int64 b = 0x1111111111111111;

int pop15(short x) {

???? unsigned __int64 y;

???? y = x * a;

???? y = y & b;

???? y = y * b;

???? y = y >> 60;

???? return y;

}

?

// 生成一個包含4 8 位部分和的字。然后,盡可能把這些字加起來后,生成一個全字和。

// 相加不會產生溢出的8 位字段的字的數目是floor(255/8) = 31

int pop_array(unsigned int A[], int n) {

???? int i, j, lim;

???? unsigned int s, s8, x;

?

???? s = 0;

???? for (i = 0; i < n; i += 31) {

???????? lim = __min(n, i + 31);

???????? s8 = 0;

???????? for (j = i; j < lim; j++) {

????????????? x = A[j];

????????????? x = x - ((x >> 1) & 0x55555555);

????????????? x = (x & 0x33333333) + ((x >> 2) & 0x33333333);

????????????? x = (x + (x >> 4)) & 0x0F0F0F0F;

????????????? s8 = s8 + x;

???????? }

???????? x = (s8 & 0x00FF00FF) + ((s8 >> 8) & 0x00FF00FF);

???????? x = (x & 0x0000FFFF) + (x >> 16);

???????? s = s + x;

???? }

???? return s;

}

?

void test5();

void main()

{

???? test5();

}

?

?

void test5()

{

???? srand((unsigned)time(NULL));

???? unsigned int a[256] = {0}; int i;

?

???? for (i = 0; i < 256; i++) {a[i] = i;}

???? cout << pop_array(a, 256) << endl;

?

???? for (i = 0; i < 256; i++) {a[i] = 1;}

???? cout << pop_array(a, 256) << endl;

?

???? for (i = 0; i < 256; i++) {a[i] = 0;}

???? cout << pop_array(a, 256) << endl;

?

???? for (i = 0; i < 256; i++) {a[i] = -1;}

???? cout << pop_array(a, 256) << endl;

?

???? for (i = 0; i < 256; i++) {a[i] = rand()%256;}

???? cout << pop_array(a, 256) << endl;

}

void test4()

{

???? short x;

?

???? x = 0x7FFF; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x0001; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x4000; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x5555; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x2AAA; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x3333; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x2CCC; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x7FFF; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x5B93; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x2C64; hex(x); cout<< dec << pop15(x) << endl;

?

???? x = 0x8000; hex(x); cout<< dec << pop15(x) << endl;

?

}

void test3()

{

???? unsigned char x;

?

???? x = 0x7F; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0xFF; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0x0; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0xAC; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0x80; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0xBD; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0x55; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0xAA; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0x0F; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0xF0; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0xE4; hex(x); cout<< dec << pop8(x) << endl;

?

???? x = 0x110; hex(0x110); cout << dec << pop7(x) << endl;

}

void test2()

{

???? char x;

?

???? x= 0x7F; hex(x); cout << dec << pop7(x) << endl;

?

???? x= 0x0; hex(x); cout << dec << pop7(x) << endl;

?

???? x= 0x0F; hex(x); cout << dec << pop7(x) << endl;

?

???? x= 0x70; hex(x); cout << dec << pop7(x) << endl;

?

???? x= 0x55; hex(x); cout << dec << pop7(x) << endl;

?

???? x= 0x2A; hex(x); cout << dec << pop7(x) << endl;

?

???? x= 0x5D; hex(x); cout << dec << pop7(x) << endl;

?

???? x= 0x33; hex(x); cout << dec << pop7(x) << endl;

?

???? x= 0xF0; hex(x); cout << dec << pop7(x) << endl;

}

void test1()

{

???? int x;

?

???? x = 0x7FFFFFFF; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = 0; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = -1; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = 1; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = 0xABCDE123; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = 0x87654321; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = 0x55555555; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = 0x80808080; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = 0xABC5DEFA; hex(x); cout<< dec << pop6(x) << endl;

?

???? x = 0X80000000; hex(x); cout<< dec << pop6(x) << endl;

}

?

?

總結

以上是生活随笔為你收集整理的种群计数 (pop_count)的全部內容,希望文章能夠幫你解決所遇到的問題。

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