C/C++刁钻问题各个击破之位运算及其应用实例(1) (二)

2014-11-24 12:52:41 · 作者: · 浏览: 1
运算范畴,这里就不赘述了。

位运算应用实例2:进制转换

要求:分别实现十进制整数按二进制、十六进制输出。

两种方法实现按二进制输出:

方法1:由于整数在计算机中是按二进制存储的,我们只需要将其每个bit按顺序打印出来即可,如果某位为1,则打印字符‘1’,否则打印字符‘0’。我给出的代码如下:

voidprintBinary(int num)

{

for(int i=0;i<32;i++)

{

cout<<((num>>(31-i))&1);

//cout<<( (num &(1<<(31-i))) ==0 0 : 1 );

}

}

其中被注释掉的那个cout与没注释的cout有同样的功能!这个函数的思路很简单,就是从高到底逐位打印每个bit。我上面的代码有一点不好的地方,那就是语句太复杂,一个cout语句干了太多的事情,如果影响您的理解,那么你可以增加几个临时变量,然后把它拆分成多个简单语句。我这么写主要是考虑到篇幅的原因,因此程序段太占篇幅了。随便说一句,编程时,语句力求简单明了:一行只写一条语句,一条语句只干一件事情!

方法二:利用bitset来实现

bitset是标准库提供的一个类(不是容器),利用它就可以很方便地操作位,下面是用bitset来实现的程序:

voidprintBinary(int num)

{

bitset<32> bits =bitset<32>((unsigned long)(num));

for(int i=31;i>=0;i--)

{

cout<<(bits[i]==true '1' : '0');

}

}

备注:关于bitset重载了多个运算符,其中包含下标运算符:[],可以方便地取得某一个bit,看它是否为1。关于bitset的更多信息请查阅msdn或者其他资料,你只要记住bitset是标准库提供的,你可以随时使用,不要忘记添加相应的头文件。

实现按16进制输出:

同样由于数据在内存中是按二进制存储的,因此将整数按照16进制输出我们可以如下做:从左向右,每4位bit一组,组合成一个十六进制数,一次输出即可,其程序如下:

void printHex(int num)

{

for(inti=28;i>=0;i-=4)

{

int temp =num>>i;

temp =temp&15; //15是掩码!

char ch;

temp>9 (ch ='A'+temp-10):(ch = '0'+temp);

cout<

}

}

该程序与上面的printBinary函数非常相似,要注意的是i每次变化4,最关键点在于语句temp= temp&15;由于是16进制,因此这里用15做掩码。我想有了printBinary做铺垫,理解这个printHex并不难,这里不赘述了。接下来我将对这两个函数进行个小小的扩展:实现整数按2n (2的n次方)进制输出!比如按8进制,32进制等。为了方便描述,我们限制1<=n<=6;并用字符’0’到’9’表示数字0到9,用字符A,B,……Z,a,b,……表示数字10到63。程序如下:

void print2powerN(int num,int N)

{

for(inti=32-N;i>=0;i-=N)

{

int temp =num>>i;

temp =temp&((1<

char ch;

if(temp<=9)

{

ch ='0'+temp;

}

elseif(temp<=35)

{

ch ='A'+temp-10;

}

else

{

ch = 'a'+temp - 36;

}

cout<

}

}

备注:用位运算也能实现十进制到任意进制的转换,这个问题比较难,我暂时还没弄透彻!

位运算案例3:求整数的二进制表示中1的个数

问题描述:输入一个整数N要求输出其二进制表示中1的个数M,比如N=13,则M=3;

分析:该问题的求解方法不止一种,可以对二进制表示的每一位逐位扫描来实现,这种方法的复杂度是o(n)其中n是N的二进制表示的总位数。这里介绍如何用位操作来求解,并且保证其复杂度低于o(n),事实上该方法的复杂度为o(m),其中m是N的二进制标识中1的个数!

思路:在讲述具体实现时,来看这样一个事实:n&(n-1)能实现将最低位的1翻转!比如说n=108,其二进制表示为01101100,则n&(n-1)的结果是01101000。因此只要不停地翻转n的二进制的最低位的1,每翻转一次让计数器+1,直到n等于0时,计数器中就记录了n的二进制中1的位数,程序如下:

int count1Bits(long n)

{

int count =0;

while(n)

{

count++;

n&=(n-1);

}

return count;

}

注:关于该问题的其他方法,请参考《编程之美》。n&(n-1)的另外一个用处是判断n是否是2的整数次幂。

到此,本文该结束了,我发现最近我每次写的东西可以用一句谚语来形容:懒婆娘的裹脚——又臭又长!没办法,每次一想写东西,就思维很发散(或许用凌乱来形容更加贴切),看来以后得把大的专题篇总结了。还有,由于最近天气奇热,心情浮躁,头脑发昏,文中的代码有考虑欠佳的地方,还请各位批评指正。