编程之美学习笔记2.1求二进制数中1的个数

来源:互联网 发布:ubuntu 开机任务栏没了 编辑:程序博客网 时间:2024/06/02 05:31

对于一个字节(8bit)的无符号整型变量,求其二进制表示中1的个数,要求算法的执行效率尽可能高。
#define BYTE unsigned char//对于一个字节的无符号整型变量v求二进制数v中1的个数int count1(BYTE);int count2(BYTE);int count3(BYTE);int count4(BYTE);main(){   BYTE i=00000111;int n;n=count4(i);printf("%d\n",n);}//int count1(BYTE v){int k=0,num=0,j=0x01;for(k=0;k<8;k++){if(v&j==1)num++;v=v>>1;}return num;}int count2(BYTE v ){int num = 0;while(v){num+=v&0x01;v>>=1;//v=v>>1}return num;}//v除以2若余数为1,则表示最后一位为1int count3(BYTE v){int num=0;while(v){if(v%2==1){num++;}v=v/2;}return num;}//利用v&(v-1)将二进制数v的最低位为1的变为0int count4(BYTE v){int num=0;while(v){v&=(v-1);num++;}return num;}
算法1 是未看解析所写,比较冗余,for循环可以直接用while()循环替代,避免重新定义循环变量;

算法2采用除法求余,余数为1则表示最后一位为1 ,再修改v=v/2。

由于除法效率较低,算法3采用位操作,但是算法1,2,3的时间复杂度都是Olog2(v),即二进制数的位数,如16为5位。算法4利用n&(n-1)每次将最低位为1的改为0,这样算法复杂度只与二进制数中1的个数有关,时间复杂度O(M),M为二进制表示中1的位数。

由于8位二进制数只有256种,可以求出每个数对应的二进制表示的1 的个数,可以采用查表法,时间复杂度为O(1)。通过“空间换时间”来获取高的时间效率是一个常用的方法。

扩展问题中对于两个二进制数A和B,问把A变为B需要改变多少位。可以直接C=A^B,(异或)再求C中的1的个数。
关于异或:

位相同为0,不同为1;与1异或,使特定位翻转;与0异或,保留其值;在swap(a,b)中可采用异或表达式省去临时变量 a=a^b;b=b^a;a=a^b;




0 0