//高效程序的奥秘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)相关推荐

  1. 【人工智能算法】受大自然启发的算法之种群、计分和选择

    本文重点: 种群 精英 计分 选择 选择算法的可伸缩性 理解种群 种群即居住在一个地方的一群特定种类的人或动物.在机器人工智能中,种群是解决问题的一组潜在方法,这些潜在解属于同一种类,因为他们解决相同 ...

  2. Nature Reviews:拥抱未知:解析土壤微生物组的复杂性

    Fierer N. Embracing the unknown: disentangling the complexities of the soil microbiome. Nature Revie ...

  3. 《算法心得:高效算法的奥秘(原书第2版)》

    <算法心得:高效算法的奥秘(原书第2版)> 基本信息 原书名:Hacker's Delight,Second Edition 原出版社: Addison-Wesley Profession ...

  4. 找工作笔试面试那些事儿(15)---互联网公司面试的零零种种和多家经验

    作者:寒小阳 时间:2013年9月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/11400719. 声明:版权所有,转载请注明出处,谢谢 ...

  5. 希尔伯特曲线 java_《算法心得:高效算法的奥秘》PDF 下载

    图书目录: 译者序 序(第1版序) 前言 第1章 概述 1.1 记法 1.2 指令集与执行时间模型 1.3 习题 第2章 基础知识 2.1 操作最右边的位元 2.1.1 德摩根定律的推论 2.1.2 ...

  6. AgriPest:A Large-Scale Domain-Specific Benchmark Dataset for Practical Agricultural Pest Detection

    论文下载地址:AgriPest论文 论文code和dataset:code和dataset 目前在GitHub上面已经找不到了.如果需要code和dataset的直接与论文作者联系可能比较好. Agr ...

  7. 微机原理—定时计数控制接口

    别看题目很高深,其实就是很简单的定时器和计数器而已. 通常用手机定个闹钟,就是定时器的使用. 工厂里通过传送带上安装传感器,传感器传输给计算机的信号用来计数. 这是一些很简单的应用,通过很小的一个芯片 ...

  8. nvGRAPH三角形计数和遍历示例

    nvGRAPH三角形计数和遍历示例 #include " stdlib.h" #include" inttypes.h" #include" stdi ...

  9. hdu5701-中位数计数

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5701 题目: Problem Description 中位数定义为所有值从小到大排序后排在正中间的那个 ...

最新文章

  1. python 显示图片然后延时,python – ROS图像用户滞后
  2. 面向容器技术资源调度关键技术深度对比
  3. 以面向对象的思想实现数据表的添加和查询,JDBC代码超详细
  4. 树莓派html5播放器,树莓派|5 个很适合在课堂上演示的树莓派项目
  5. linux fips 模式,linux – FIPS Capable OpenSSL交叉编译:内容指纹问题
  6. C语言 最小二乘 向量旋转 欧拉方法求洛伦兹方程
  7. JNuit4实战技巧总结
  8. 2020年吉林省玉米种植分布数据/作物分布数据
  9. 创建用户, 使用crontab定时运行程序
  10. D轮融资1亿美金,6亿美金估值,3位计算机学霸如何带领海归团队创造业内神话?!
  11. 产品需求文档(PRD,Product Requirement Document)模板
  12. CDA I级学习 - CDA I级报名
  13. 白话ES 的分布式架构原理
  14. 全面对战LILO 和 GRUB
  15. 关于流程图的场景提炼,这一次终于说清楚业务流程图、功能流程图、页面流程图了
  16. RabbitMQ-operation queue.declare caused a channel exception precondition_failed错误
  17. hotmail手机端_如何在安卓手机上设置Hotmail?
  18. 工业交换机智能监控管理方案
  19. LeetCode数据库题目汇总一(附答案)
  20. MOOC浙大数据结构课后题记录——PTA数据结构题目集(全)

热门文章

  1. android 图片缩放算法,Android大图加载,缩放,滑动浏览--SubsamplingScaleImageView 源码分析大图加载...
  2. 成功解决Error:invalid character in identifier
  3. 成功解决OSError: cannot open resource self.font = core.getfont(font, size, index, encoding, layout_engin
  4. BC之CM:区块链之共识机制——深入浅出以及国内外当下主流区块链平台共识机制纵向、横向比较相关配图
  5. pyhanlp 提取关键词、自动摘要
  6. 机器学习-特征工程中的样本不均衡处理方法
  7. xshell xftp使用
  8. A.01.01—模块的输入—低端输入
  9. Intent 匹配规则
  10. sum() over() 函数的使用