关于按位异或运算符 ^
运算规则:参与^运算两个二进制位不同时,结果为 1,相同时结果为 0。
例:2^5 ===> 0010 ^1001 ===> 1011
特别的:
0^5 =5 0000^1001 ===>1001
15^10=5 1111^1010 ====> 0101
总结 :
- 按位异或运算可以用来将某些二进制位反转
将需要反转的对应位异或二进制的1,则实现反转 - 0跟任何一个整数异或值不变
案例一: 数组中所有数都是成对出现,只有一个数只出现一次,找出这个数
- 分析:根据异或规则,相同的数异或为0,0跟任何一个整数异或 值不变
- C程序实现:
#include <stdio.h>
int one_array(int*,int);
int main()
{
int a[] = {2,4,6,5,4,2,6};
int len = sizeof(a)/sizeof(a[0]);
int num = one_array(a,len);
printf ("num = %d\n", num);
return 0;
}
int one_array(int a[],int len)
{
int i;
int num=0;
for(i=0;i<len;i++)
{
num^=a[i];
}
return num;
}
案例二: 数组中所有数都是成对出现,有两个数只出现一次,找出这个两个数
- 分析:我们还利用案例一的解决方法,但是有两个不同数,将数组元素全部异或并不能得出两个数,那么我们选择把这两个数分开,分成两个数组,怎么分开呢?根据什么条件能把他们分开呢?
首先,我们来看两个不同的数的异或:
1^3 ===> 0001^0011 = 0010
从二进制的角度来看,1不同于3,就是有对应的位是不同的
从异或结果上来看,不同的位异或结果为1
那么好,我们有条件了,可以根据异或结果 第一个为1的位数来分组。还是1和3,我们可以根据他们二进制第二位是0还是1把他们分开,1二进制第二位是0,3二进制第二位是1。 - C程序实现:
#include <stdio.h>
int main()
{
int a[]={1,5,2,5,4,1};
int len=sizeof(a)/sizeof(a[0]);
int num =0;
int num1=0;
int num2=0;
//第一步:将数组元素全部异或,得出两个不同的数异或结果
int i;
for(i=0;i<len;i++)
{
num^=a[i];
}
//第二步:找出异或结果二进制的第一个1的位数
int count=1;
while(0==num&1)
{
num>>=1;
count++;
}
//第三步:分组异或
for(i=0;i<len;i++)
{
if((a[i]>>count)&1)
{
num1^=a[i];
}
else
{
num2^=a[i];
}
}
printf("num1=%d num2=%d\n",num1,num2);
return 0;
}