300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 编程之美 2.1 求二进制中1的个数

编程之美 2.1 求二进制中1的个数

时间:2019-05-16 22:14:05

相关推荐

编程之美 2.1 求二进制中1的个数

问题描述:

对于1个字节(8bit)无符号整型变量,求其二进制表示中“1”的个数

解法一:除2取余

(对于二进制操作,除以一个2,原来的数字会减少一个0。如果除的过程中有余数,就表示当前位置有一个1)

int Count(BYTE v){int num = 0;while(v){if(v%2==1)num++;v=v/2;}return num;}

解法二:位移操作

(对于二进制向右移位操作同样可以达到解法一的目的,但是比除、余操作效率高)

int Count(BYTE v){int num = 0;while(v){num+=v&0x01;v>>=1;}return num;}

解法三:

只考虑有1的情况(清除最低位的1)

int Count(BYTE v){int num = 0;while(v){v&=(v-1);num++;}return num;}

解法四:分支操作

(看似直接,但是执行效率可能会低于解法二、三)空间换时间

int Count(BYTE v){int num = 0;switch(v){case 0x0:num = 0;break;case 0x1:case 0x2:case 0x4:case 0x8:case 0x10:case 0x20:case 0x40:case 0x80:num = 1;break;case 0x3:case 0x6:case 0xc:case 0x18:case 0x30:case 0x60:case 0xc0:num = 2;break;//...}return num;}

解法五:查表法

空间换时间

把0~255中“1”的个数直接存储在数组中,v作为数组下标,countTable[v]就是v中“1”的个数。算法时间复杂度仅为O(1)

int countTable[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};int Count(BYTE v){return countTbale[v];}

扩展问题:

问题1:对于32位的DWORD,可以动态建表或静态建表

1)动态建表

由于表示在程序运行时动态创建的,所以速度上肯定会慢一些,

把这个版本放在这里,有两个原因

1.填表的方法,这个方法的确很巧妙。

2.类型转换,这里不能使用传统的强制转换,而是先取地址再转换成对应的指针类型。

代码如下:

int BitCount(unsigned int n) { // 建表unsigned char BitsSetTable256[256] = {0} ; // 初始化表 for (int i= 0; i<256; i++) BitsSetTable256[i]=(i&1)+BitsSetTable256[i/2]; unsigned int c = 0 ; // 查表unsigned char *p=(unsigned char *) &n; //一个字节一个字节 c=BitsSetTable256[p[0]]+BitsSetTable256[p[1]]+ BitsSetTable256[p[2]]+BitsSetTable256[p[3]]; return c ; }

2)静态建表

首先构造一个包含256个元素的表table,table[i]即i中1的个数,

这里的i是[0-255]之间任意一个值。然后对于任意一个32bit无符号整数n,

我们将其拆分成四个8bit,然后分别求出每个8bit中1的个数,再累加求和即可,这里用移位的方法,每次右移8位,并与0xff相与,取得最低位的8bit,累加后继续移位,如此往复,直到n为0。所以对于任意一个32位整数,需要查表4次。以十进制数2882400018为例,其对应的二进制数为10101011110011011110111100010010,对应的四次查表过程如下:红色表示当前8bit,绿色表示右移后高位补零。

第一次(n & 0xff) 10101011110011011110111100010010

第二次((n >> 8) & 0xff) 00000000101010111100110111101111

第三次((n >> 16) & 0xff)00000000000000001010101111001101

第四次((n >> 24) & 0xff)00000000000000000000000010101011

代码如下:

int BitCount7(unsigned int n){ unsigned int 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[n & 0xff] +table[(n >> 8) & 0xff] +table[(n >> 16) & 0xff] +table[(n >> 24) & 0xff] ;}

2.问题2,给定A和B,问把A变为B需要改变多少位?也就是说有多少位不同?

首先异或,则不同的位结果为1,然后统计异或结果中1的个数;

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。