分享

巧妙地移位运算

 icecity1306 2014-09-03

       恰当的移位运算总是能够让代码显得很简洁、很优雅,下面,就让我们来看一下编程中使用频率比较高的一些移位运算:

       本程序在VS2010编译器下运行,VS2010中,int占4个字节(32位),下面程序也只针对int型变量(常量)进行考虑。

 

Cpp代码  收藏代码
  1. // shiftOperation.cpp : 定义控制台应用程序的入口点。  
  2. /******************************************* 
  3.   author:老六是Jerry 
  4.   functoin:位运算 
  5. ********************************************/  
  6.   
  7. #include "stdafx.h"  
  8. #include <Windows.h>  
  9. #include <iostream>  
  10. using namespace std;  
  11.   
  12. int _tmain(int argc, _TCHAR* argv[])  
  13. {  
  14.     //获得int型最大值  
  15.     cout<<((1<<31)-1)<<endl;    //int占4个字节,共可以表示2^32个数,由于可以表示负数,所以最大数为2^31-1(最高位为符号位)  
  16.     //获得int型最小值  
  17.     cout<<(1<<31)<<endl;    //int型表示的负数的最小值  
  18.     cout<<"==============================\n";  
  19.       
  20.     //判断奇偶性  
  21.     int p=12344;  
  22.     if((p&1)==1)    //非常简单的道理,奇数用二进制表示最后一位一定为1,而偶数最后一位一定是0,所以与1(末位为1,其它全0)做与操作即                      可判断  
  23.     {  
  24.     cout<<p<<"是奇数!"<<endl;  
  25.     }  
  26.     else  
  27.     {  
  28.     cout<<p<<"是偶数!"<<endl;  
  29.     }  
  30.     cout<<"==============================\n";  
  31.   
  32.     //不用临时变量交换两个数  
  33.     //1.不用移位操作实现  
  34.     int a=2,b=3;  
  35.     a=a*b;  
  36.     b=a/b;  
  37.     a=a/b;  
  38.     cout<<a<<","<<b<<endl;  
  39.     int c=4,d=5;  
  40.     c=c+d;  
  41.     d=c-d;  
  42.     c=c-d;  
  43.     cout<<c<<","<<d<<endl;  
  44.     //2.移位操作实现  
  45.     int e=6,f=7;  
  46.     //e=e^f;    //第一步按位异或相当于把e和f不同的位找出来,存入e中,不同的位值为1 (设e^f=g(g的值存在e中))  
  47.     //f=f^e;    //第二步将f与得到的不同的位的值按位异或,即会得到另一个值(e^f=g -->  f^g=e)    
  48.     //e=e^f;    //第三步f已经转换为原来的e,所以用f和现在的e(存的是不同的位的信息)按位异或即可得到原f的值  
  49.     //上面三步可以写成一步  
  50.     e^=f^=e^=f;     
  51.     cout<<e<<","<<f<<endl;  
  52.     cout<<"==============================\n";  
  53.   
  54.   
  55.     //取绝对值  
  56.     //原理:正数(考虑int类型)右移31位之后等于0,负数右移31位之后等于-1  
  57.     int h=-6;  
  58.     cout<<((h^(h>>31))-(h>>31))<<endl;  
  59.     //若h是正数,h^0-0=h,值不变  
  60.     //若h是负数,h^(-1)+1,将h的补码与-1的补码按位异或,再加1,得到绝对值  
  61.     cout<<"==============================\n";  
  62.   
  63.   
  64.     //取两个数的较小、较大值  
  65.     int i=2,j=3;  
  66.     //取两数的较大值    
  67.     cout<<((j&((i-j)>>31)) | (i&(~(i-j)>>31)))<<endl;    //若i-j>=0,右移31位后为0,j&0=0;~(i-j)右移31位之后为-1,i&-1=i                                                           (-1的补码为1111...1111)   
  68.     //取两数的较小值  
  69.     cout<<((i&((i-j)>>31)) | (j&(~(i-j)>>31)))<<endl;    //同理   
  70.     cout<<"==============================\n";  
  71.   
  72.   
  73.     //判断一个数是不是2的幂  
  74.     int k=31;  
  75.     cout<<((k&(k-1))==0)<<endl;    //若一个数是2的幂,则这个数转换为二进制后应该只有一位值为1(符号位除外),-1之后此位置0,后面                                     的位全置1  
  76.     cout<<"==============================\n";  
  77.   
  78.   
  79.     //求两个整数的平均值  
  80.     int m=6,n=8;  
  81.     //简单方法,先相加再除以2  
  82.     cout<<((m+n)>>1)<<endl;  
  83.     //另一方法  
  84.     cout<<((m^n)>>1)+(m&n)<<endl;    //m^n得到两数的对应位中有且仅有一个为1的部分,并除以2,m&n得到对应位都为1的部分,即得到平                                        均值  
  85.     cout<<"==============================\n";  
  86.   
  87.     Sleep(5000);  
  88.     return 0;  
  89. }  

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多