聊聊“异或”位运算

        一、异或的性质

        异或的概念还是比较好理解:相同为0,不同为1。不过以前对异或的性质却没有较为深入的了解。

        1、异或操作满足交换律和结合律:a^b=b^a;  a^b^c=a^(b^c);

        2、0与任何变量异或,结果为这个变量:a=0^a;

        3、任何变量与其自己异或,结果为0:0=a^a;

        举个例子:如果要交换两个变量的值,一般的方法是需要定义一个中间变量,然后交换两个变量的值;但是也可以用异或的操作交换两个变量的值,如下所示:

#include<stdio.h>

int main(void)
{
	int a=1;
	int b=2;
	a=a^b;
	b=a^b;/*把上式带入:b=a^b^b=a*/
	a=a^b;/*把上式带入:a=a^b^a=b*/
	printf("%d,%d",a,b);
	return 0;
}

     不需要中间变量,仅用异或的操作就交换了两个变量的值。不过在用这种方法前,必需确保两个变量位于不同的存储位置:比如交换a和a的值,会把a变成0。所以这种方式是一种小聪明,并不提倡。

        二、做两个题

        1、一个数组中,只有一个变量出现了奇数次,其余变量都出现了偶数次,求出现奇数次的这个变量。

#include<stdio.h>

int exor(int array[],int length);

int main(void)
{
	int a;
	int array1[7]={1,2,3,2,3,1,5};
	a=exor(array1,7);
	printf("%d",a);
}

int exor(int array[],int length)
{
	int odd=0;
	int i;
	for(i=0;i<length;i++)/*异或遍历数组,出现奇数次的变量经过异或遍历为变量本身,出现偶数次的变量经过异或遍历为0*/
	{
		odd^=array[i];
	}
	return odd;
}

        2、一个数组,只有两个变量出现了奇数次,其余变量都出现了偶数次,求这两个出现了奇数次的变量。

int exor(int array[],int length)
{
	int eor=0;
	int one=0;
	int elseone;
	int i,c;
	for(i=0;i<length;i++)/*假设两个出现奇数次的变量为a和b,异或遍历数组,得到两个变量异或后的结果:a^b*/
	{
		eor^=array[i];
	}
	/*因为a,b肯定不相等,所以a^b肯定不为0,所以enr肯定有一位为1,通过这一位,将数组分类,a,b属于不同的类*/
	c=((~eor)+1)&eor;/*通过取反加一,再与原值相与,得到c为:enr最右侧不为0的位保留,其余位都置0*/
	for(i=0;i<length;i++)
	{
		if((array[i]&c)==0)
		{
			one^=array[i];
		}
	}
	elseone=one^eor;
	return 0;
}

        这份代码中需要注意两点,一是:取反加一再与原值相与,做到只保留最右侧的1。二是:按位与的优先级竟然低于比较运算符。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值