位运算

  众所周知,我们存储在计算机中的数都是以二进制的形式存在的,但是我们在平常的编写代码和使用中都是习惯使用十进制来进行操作的,但是直接对数进行二进制的操作会有意向不到的效果哦。

  让我们看看有哪些常用的位运算符:

a b ~a(非/取反) a&b(与) a|b(或) a^b(异或)
 1 1 0 1 1 0
 1 0  0  0 1  1
 0  1  1  0  1  1
0 0 1 0 0 0

  除了这些之外还有移位运算符<<(右移),>>(左移),>>>用0来填充高位,以及>>运算符用符号位来填充高位(记住是没有“>>>”运算符的哦)。举几个简单的例子1001>>2得到10;10<<2得到1000;对于int类型,1<<36和1<<4得到的结果是一样的(模32)(java中可以这样,但是C++中好像会出现错误)。

  接下来让我们看看一些可以在日常的编码中用到的(可以装逼!!)知识:

  1.判断奇偶数:X&1==1则为奇数,反之则为偶数

  2.交换两个整数变量的值

1 int a,b;
2 a=1;
3 b=3;
4 a=a^b;
5 b=a^b;//a^b^b->a得到a
6 a=b^a;//a^a^b->b得到b
7 cout< 
 

  3,不用判断语句得到整数的绝对值:~a+1.

   接下来简要介绍下^(xor)异或的应用,异或可以理解也不进位的加法:

    1.交换律   a^b=b^a;

    2.结合律  a^(b^c)=(a^b)^c

    3.自反性  a^b^b=a^0=a

    4.对于任意的x,x属于整数,都有x^x=0,x^0=x

  上面我们谈论了这么多的理论知识,光说不练假把式,来看几个实际的题目吧!

  题目一:从1-1000这一千个数放在大小为1001的数组中,其中有一个数重复,将它找出来,不使用辅助空间。

  题解:可以使用异或中a^0=a,a^a=0。同一个数进行偶数次的异或运算会等于0,进行奇数的异或运算得它本身,所以可以根据这个思想来解决这个题目。

 1 #include
 2 #include
 3 #include
 4 #include
 5 using namespace std;
 6 
 7 int main(){
 8     int a[1001];
 9     for(int i=0;i<1000;i++) a[i]=i+1;
10     a[1000]=rand()%1000+1;
11     swap(a[1000],a[rand()%1000]);//将重复的数与随机的一个下标的数组元素互换 
12     int x=0;
13     for(int i=1;i<=1000;i++) x^=i;
14     for(int i=0;i<1001;i++) x^=a[i];
15     cout<endl;
16     return 0;
17  }

  题目二:在以系列的数中,有k个数出现了k次,只有一个数出现过一次,找到这个只出现过一次的数。

  题解:首先我们需要知道“k个k进制的数进行不进位的加法得0”,其实可以这么来看k个k进制的数相加可以看作乘以k,也就是需要向右移位,但是由于进行的是不进位的加法,所以我们进行向右移位后就得0了。

    解这个题目,首先我们需要将这一系列的数全部转换为k进制的数(辗转相除法可以实现十进制数转换为k进制的数),然后我们需要进行不进位的加法,这个可以将每一位上的数相加后模k实现。具体的代码就不细说了。

 

 

 

你可能感兴趣的:(位运算)