计算二进制数中1出现的次数

来源:互联网 发布:2017成都软件行业 编辑:程序博客网 时间:2024/06/05 19:42

计算二进制数中1出现的次数

概述:

给定一个数,如32位的int类型的整数,由于计算机中存储都是用二进制的形式,所以计算给出的这个整数中出现1的次数

下面介绍一共五种方法:
一、mod 2

对一个整数除以2,如果整除,原来的数字就会少一个最低位的0,否则出现余数则说明最低位是1,下面给出C++代码:

//mod 2int version1(int a){    int count = 0;    while (a)    {        count += a % 2;        a /= 2;    }    return count;}

二、mod 2(位操作)

原理同方法一,不同的地方在于,这里的求余和除法都用了位操作来完成,下面给出C++代码:

//mod 2 with bit operationint version2(int a){    int count = 0;    while (a)    {        count += (a & 0x00000001);        a >>= 1;    }    return count;}

三、直接计算1出现的次数

上两种方法时间复杂度都是和数字的二进制码长度有关的,而如果二进制码长度很长而出现1的个数很少的时候,效率就不是太高,下面给出一个方法,循环次数只跟1出现的次数有关系:

//count Ones directlyint version3(int a){    int count = 0;    while (a)    {        a &= a - 1;        count ++;    }    return count;}

四、网上看到的一种方法

这个方法是网上看到的,他的介绍说是二分法,但是看不太懂,也放上来~好处就是会更快,因为都是位操作而且没有循环,时间复杂度就是O(1)

//bisectionint version4(int a){    a = a - ((a >> 1) & 0x55555555);    a = (a & 0x33333333) + ((a >> 2) & 0x33333333);    a = (a + (a >> 4)) & 0x0F0F0F0F;    a = a + (a >> 8);    a = a + (a >> 16);    return a & 0x0000003F;}

五、查表

预先把出现1的个数记起来,存在一个数组里,不用计算,直接读取。比如先把8位的出现1的个数用数组记录下来,也就是一个256长度的数组,每个数组的元素就是对应下标的数的二进制码出现1的次数,然后把32位的int分成4段来判断,再把每个加起来,由于需要把表计算出来,这里就不写上来了~

总结

最基础的算法就是方法一,然后存在优化的地方就是把求余、除2等变成位操作,找到更低复杂度的计算方法(如一个m位的二进制数,有n位是1,则n <= m,那么能否找到O(n)而不是O(m)的方法,也或者是方法四那种更快的O(1)的方法)。虽然问题很简单,但是给我的启示就是一个优化的问题,先分析最耗费时间的部分,然后再对这个部分进行优化,循环直到达到预期为止~

0 0
原创粉丝点击