异或(^)的含义与基本用法
异或(^)的含义与基本用法
异或的含义
异或(^)和与运算(&)、或运算(|)都是位运算,因为计算机的运算都是将数据转换成二进制来进行的,所以一般来说,位运算比加减乘除的算数运算快得多。异或的运算法则如下:
1 ^ 0 == 1
1 ^ 1 == 0
0 ^ 0 == 0
即相同为0,不同为1。
异或的运算性质
异或有几大运算性质:
交换律: ab==ba
结合律: aba==aab
任何非0的数和0异或的结果都是它本身
任何数和自己本身异或的结果都为0
如果你看到这里,感觉上面列的运算法则和性质有所冲突的时候,请考虑进制不同的情况。本质上异或是在二进制层面上的,这是它的运算法则,当直观表现在十进制上的,才是它的运算性质。
在二进制层面上,异或的运算可以看成是无进位相加,举个例子
10101101100011^ 0110101
相加的两个二进制数,从右往左数第二位上都是1,1+1本来应该进位1,本位变成0的,然后^运算,无进位,所以结果直接写成0。这样的理解在后续的运用中能更加形象的帮我们解释一些结果。
就此,异或的运算性质也概括完了,接下来让我们看看它的运用情况。
异或的运用
在需要交换两个变量的值时,你是否马上想到再设置一个中间变量来进行交换?那么如果我跟你说不用中间变量,两者可以直接交换呢?下面我们就用异或来实现
void swap(int a,int b)
{a=a^b;b=a^b;a=a^b;
}
这样三个格式一样的语句就完成了值的交换,是不是觉得很不可思议?下面我们来分析一下,加深对异或的理解。
在第一条语句结束后,分析一下a,b的值:a=a^b b=b;
在第二条语句结束后,分析一下:a不变,a=a^b 分析b我们先交换律,再结合律:b=ba=b(a^b);
这里我们对b的值进一步化简,因为性质——任何数跟它自己异或的结果都为0,所以b=a^0=a
最后分析第三条语句,a=ab=(ab)^a,同理,a=b;
就此,我们完成了a,b值的交换。
但需要注意的是,这种方法其实是抖机灵的做法,它的可读性很差。同时使用它有一个隐藏的限制条件,即交换的两值在内存空间中并不能属于同一区域,如排序数组中元素的值,因为当它们为同一性质的东西,即两者完全相同时,使用异或将会使它们都归零。
下面我们来看两个有关异或的实际问题:
Q1:在一堆数中,只有一种数,它出现了奇数次,而其他种的数,都出现了偶数次。请找出出现了奇数次的这种数。
直接上代码:
int arr[20];int i,a;for(i=0;i<20;i++){a^=arr[i];}//a就是出现奇数次的数
为什么这么说?结合两点,第一点,异或的性质,任何数和它本身异或的结果都是0;第二点,根据题意,除了需要找的这个数以外,其他数都能找到和它自己相同的数两两配对变成0。最后可以化简成该数^0,答案浮出水面。
Q2:在一堆数中,有且仅有两种数,出现了奇数次,而其他种的数,都出现了偶数次,请找出出现了奇数次的这两种数。
上代码:
int main()
{ int a=0,b=0;//设出现奇数次的数为a,bint t=0,i;int rightone;//二进制下,从右往左的第一个1int arr[20];for( i=0;i<20;i++){t^=arr[i];}//现在的t==a^b,这两个出现奇数次的数异或//因为t==a^b;//a!=b//所以t的二进制肯定有一位上是1rightone=t&(~t+1);//一个数与(&)上自己取反+1的数,结果得到这个数二进制下最右侧的1//并且我们知道,a和b两者在这一位上,只有一者位上是1,另一个一定是0.for(i=0;i<20;i++){if(t^arr[i]==0)//将该最右位是1和0的区分开{a^=arr[i];//此时a等于一种奇数次数^一些出现过偶数次数且该位也是1的数//而出现偶数次可以抵消,所以直接得到了第一个出现了奇数次的数}}b=t^a;//由此再得到b
}
以上有两个难点,第一是得到一个数二进制下最右侧的1所在的位置,为该数&(~该数+1),即原码&补码,不明白的用几个二进制数试验即可,记住以后多可以拿来套用。
第二个是当我们用一个变量t异或了一轮数组后,得到了a^b,之后我们的第二轮异或,是有选择性的异或。如此便区分出了以下情况:
一侧 | 另一侧 |
---|---|
出现过奇数次的a | 出现过奇数次的b |
出现偶数次且最右位为1的数 | 出现偶数次且最右位为0的数 |
第二轮异或的精髓就在于将a,b分开了,而其他数都是出现过偶数次,根据自己^自己==0,全部抵消,所以最后就得到了单独的a和b。
感谢阅览,希望对你有帮助。
异或(^)的含义与基本用法相关推荐
- C.武器大师的宝贝 (异或的含义)
武器大师的宝贝 题目链接https://csustacm.fun/problem/1087 Time limit1000 ms Description 武器大师有两堆宝贝箱子,每个箱子都有着自己的一个 ...
- bulk这个词的用法_雅思考试真题解析|雅思听力“正负含义词”的妙用
你一定会有很大的收获雅思听力"正负含义词"的妙用01 正负含义词的定义 语言表达的内容可以分为两大类:客观叙述和主观表达.以以下两个简单句为例: 1. 我是一个老师. 2. 我是一 ...
- 命令注入-命令的连接符【‘’‘’‘||’‘|’】的含义及其用法
命令的连接符['&''&&''||''|']的含义及其用法 一.各个连接符的含义 二.用法演示 1.a && b 2.a & b 3.a || b 4. ...
- C语言逻辑操作符的巧妙用法:an anagram of a palindrome
这是网上看到的面试题. A string is a palindrome if it has exactly the same sequence of characters when read ...
- C语言sizeof和strlen的含义,用法和区别
目录 strlen( ) strlen( )的含义 strlen( )函数的用法 sizeof( ) sizeof( )的含义 sizeof( )的用法 它俩的区别 strlen( ) strlen( ...
- 不懂异或?一文详解移位操作符,位操作符
一.移位操作符 << >> 在介绍移位操作符前先学习一下二进制的表示方法,二进制表示方法有3种: 原码,反码,补码 正数原码,反码,补码相同 负数原码,反码,补码需要计算 ...
- 异或、异或和 的性质及应用总结
一:异或的含义 或在数学中的含义:一个元素在集合A中或在集合B中,或的维恩图如下: 而异或是不允许共存的,所以 A ^ B 的维恩图如下: 同理对于 A ^ B ^ C 维恩图: 异或运算{\disp ...
- 如何理解「异或(XOR)」运算在计算机科学中的重要性
前言 在学逻辑学的时候,基本的逻辑运算是非.与.或,且并没有得到特别的强调,而且事实上异或可以由这三个逻辑运算符表出.可是在计算机领域,异或似乎处于与非.与.或并列的关系,例如 C 语言的位运算符中就 ...
- Python中self用法详解
Python中self用法详解 https://blog.csdn.net/CLHugh/article/details/75000104 首页 博客 学院 下载 图文课 论坛 APP 问答 商城 V ...
最新文章
- win7上Docker使用
- keil 多文件组织方法
- 《深入理解Java虚拟机》读书笔记
- VS-设置签出独占锁
- Sphinx 2.2.3 安装和配置,英文数字中文搜索
- AdBlock插件自定义拦截规则
- idea上传新项目至svn仓库
- 常用正则表达式匹配(中文字符)
- 第一章:【UCHome二次开发】uchome文件体系介绍
- CentOS系统查看本机IP地址
- JS实现网页截图的三种方案
- 笔记本共享网络给台式机
- 2019下半年教资信息技术学科知识与教育能力——主观题
- wp-db.php,WordPress中的数据库操作类wp-db.php
- 操作系统期末知识点浓缩总结复习
- 关于正向级数收敛而它的平方也收敛的证明
- 位置不可用无法访问 chkdsk无法修复的文件恢复方法
- Java 对象 、String 、JSON 互转
- 2021-2-11——除夕
- 微信公众号发布投票教程
热门文章
- 连载《国培计划》骨干教师的研修日志之六:关于米新江教授谈的授之以渔与渔之以渔
- Vue粒子特效(vue-particles插件) 粒子星空图
- 数据分享|R语言因子分析、相关性分析大学生兼职现状调查问卷数据可视化报告...
- 使用并查集实现查找无向图的连通分量和求解有向图的强连通分量
- 数据库连接失败:java.lang.RuntimeException: com.mysql.cj.exceptions.InvalidConnectionAttributeException
- Python中的双曲函数
- MRI:T1 T2 T1WI T2WI笔记
- 跨境电商万圣节社媒营销:8个方法助你冲出重围
- 大数据学习资料和书籍推荐
- 栈实现算术表达式求值