C语言异或操作符的经典题

今天分享两个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就会留下来,单独出现的那个数就会暴露出来,所以最后连续异
或的结果就是单独出现的那个数字。

这是非常巧妙的一个方法,所以异或这个操作符熟练使用的话还是能方便的解决不少的问题,挺神奇的一个操作符!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值