今天分享两个C语言异或操作符解决问题的经典例子:
首先讲一下异或的基本运算规则:
1^x = ~x 0^x = x
0^0 = 0 0^1 = 1
1^0 = 1 1^1 = 0
所以可以看出1和任何数异或的结果就是x取反,0和任何数的异或结果就是x本身,这是很重要的两个结果。
实例一:
不使用(a+b)/2这种方式,求两个数的平均值。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int avg1(int a, int b)
{
return a + ((b - a) >> 1);
}
int avg2(int a, int b)
{
return (a&b) + ((a^b) >> 1);
}
int main()
{
int a, b;
printf("请输入两个数:\n");
scanf("%d %d",&a,&b);
printf("avg1=%d\n",avg1(a,b));
printf("avg2=%d\n",avg2(a,b));
system("pause");
return 0;
}
讲解:首先这里有两个函数是用了两种方法。
方法一:比简单的求和方法,就是a加上a和b之间差值的一半,这样就是两个数的平均值,这个我想大家应该不难想明白,简单地说就是让两个变得一样多,右移一位相当于除2。
方法二:这个方法就难想到一些,因为他是(a&b) + ((a^b) >> 1),首先是先化为二进制进行计算,a&b求得是相同位的平均值。
举例——>
-> 这里可以看到a和b的第二位和第三位是相同的,所以a&b其实就已经得到了a和b相同位的平均值,而a^b就是得到了不同位的值,然后再除2,两者一加就是两个数的平均值。
实例二:
一组数据中只有一个数字出现了一次。其他所有数字都是成对出现的。
请找出这个数字。(使用位运算)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int get_once(int a[])
{
int ret = 0;
for (int i = 0; i < 11; i++)
{
ret ^= a[i];
}
return ret;
}
int main()
{
int a[11];
printf("请输入11个整数:\n");
for (int i = 0; i < 11; i++)
{
scanf("%d",&a[i]);
}
printf("%d\n",get_once(a));
system("pause");
return 0;
}
讲解:这道题还是很有意思的,首先要求用位运算符解决,所以就得充分利用 “^” 的性质,下面还是举个例子来讲解。
举例——>
首先异或的结果和数字的运算顺序无关,其次在连续异或运算中如果两个相同的数的异或
结果绝对为0,相当于抵消的效果,最后的结果只会保留单独出现的那个数字,从左边的二进
制序列也可以看出,一共四列,每列的1如果是奇数个最后的结果绝对会是1,如果是偶数个1
的话那结果绝对是0,多的1就会留下来,单独出现的那个数就会暴露出来,所以最后连续异
或的结果就是单独出现的那个数字。
这是非常巧妙的一个方法,所以异或这个操作符熟练使用的话还是能方便的解决不少的问题,挺神奇的一个操作符!