异或的性质及运用

今天在复习排序算法时,对于用到两个元素交换的几种算法,无意中看到另外一种交换的方法(以前是用引入一个中间变量temp实现):
int a=1;
int b=2;
a ^= b;
b ^= a;
a ^= b;
看到这个很疑惑,就去查了一下,
下面是从一个博客中看到的:
异或是一种基于二进制的位运算,用符号XOR或者 ^ 表示,其运算法则是对运算符两侧数的每一个二进制位,同值取0,异值取1。它与布尔运算的区别在于,当运算符两侧均为1时,布尔运算的结果为1,异或运算的结果为0。
简单理解就是不进位加法,如1+1=0,,0+0=0,1+0=1。
性质
1、交换律
2、结合律(即(a^b)^c == a^(b^c))
3、对于任何数x,都有x^x=0,x^0=x
4、自反性 A XOR B XOR B = A xor  0 = A
异或运算最常见于多项式除法,不过它最重要的性质还是自反性:A XOR B XOR B = A,即对给定的数A,用同样的运算因子(B)作两次异或运算后仍得到A本身。这是一个神奇的性质,利用这个性质,可以获得许多有趣的应用。 例如,所有的程序教科书都会向初学者指出,要交换两个变量的值,必须要引入一个中间变量。但如果使用异或,就可以节约一个变量的存储空间: 设有A,B两个变量,存储的值分别为a,b,则以下三行表达式将互换他们的值 表达式 (值) :
 A=A XOR B (a XOR b)
 B=B XOR A (b XOR a XOR b = a) 
 A=A XOR B (a XOR b XOR a = b)
 类似地,该运算还可以应用在加密,数据传输,校验等等许多领域。
应用举例:
1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现
一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空
间,能否设计一个算法实现?
解法一、显然已经有人提出了一个比较精彩的解法,将所有数加起来,减去1+2+...+1000的和。
这个算法已经足够完美了,相信出题者的标准答案也就是这个算法,唯一的问题是,如果数列过大,则可能会导致溢出。
解法二、异或就没有这个问题,并且性能更好。
将所有的数全部异或,得到的结果与1^2^3^...^1000的结果进行异或,得到的结果就是重复数。
但是这个算法虽然很简单,但证明起来并不是一件容易的事情。这与异或运算的几个特性有关系。
首先是异或运算满足交换律、结合律。
所以,1^2^...^n^...^n^...^1000,无论这两个n出现在什么位置,都可以转换成为1^2^...^1000^(n^n)的形式。
其次,对于任何数x,都有x^x=0,x^0=x。
所以1^2^...^n^...^n^...^1000 = 1^2^...^1000^(n^n)= 1^2^...^1000^0 = 1^2^...^1000(即序列中除了n的所有数的异或)。
令,1^2^...^1000(序列中不包含n)的结果为T
则1^2^...^1000(序列中包含n)的结果就是T^n。
T^(T^n)=n。
所以,将所有的数全部异或,得到的结果与1^2^3^...^1000的结果进行异或,得到的结果就是重复数。
当然有人会说,1+2+...+1000的结果有高斯定律可以快速计算,但实际上1^2^...^1000的结果也是有规律的,算法比高斯定律还该简单的多。
google面试题的变形:一个数组存放若干整数,一个数出现奇数次,其余数均出现偶数次,找出这个出现奇数次的数?
解法有很多,但是最好的和上面一样,就是把所有数异或,最后结构就是要找的,原理同上!!
************************************分割线*******************************************
这样可以实现不引人第三个变量实现交换,但是进行的计算相对第三个变量多,所以效率会低一些。
关于其他的方法还有:int a=5,b=10; 
a=a+b;   //a=15,b=10 
b=a-b;   //a=15,b=5 
a=a-b;   //a=10,b=5 
但是这样做有一个缺陷,假设它运行在vc6环境中,那么int的大小是4 Bytes,所以int变量所存放的最大值是2^31-1即2147483647,如果我们令a的值为2147483000,b的值为1000000000,那么a和b相加就越界了。 
事实上,从实际的运行统计上看,我们发现要交换的两个变量,是同号的概率很大,而且,他们之间相减,越界的情况也很少,因此我们可以把上面的加减法互换,这样使得程序出错的概率减少: 
int a=5,b=10; 
a-=b;   //a=-5,b=10 
b+=a;   //a=15,b=5 
a+=b;   //a=10,b=5 
通过以上运算,a和b中的值就进行了交换。表面上看起来很简单,但是不容易想到,尤其是在习惯引入第三变量的算法之后。 
它的原理是:把a、b看做数轴上的点,围绕两点间的距离来进行计算。 
具体过程:第一句“a-=b”求出ab两点的距离,并且将其保存在a中;第二句“b+=a”求出a到原点的距离(b到原点的距离与ab两点距离之差),并且将其保存在b中;第三句“a+=b”求出b到原点的距离(a到原点距离与ab两点距离之和),并且将其保存在a中。完成交换。 


### 异或运算的基本性质 异或运算具有以下几个基本性质: 1. **交换律** 对于任意两个整数 \(A\) 和 \(B\),有 \(A \oplus B = B \oplus A\)。这意味着在执行异或操作时,操作数的顺序不影响最终结果[^1]。 2. **结合律** 如果存在三个整数 \(A\)、\(B\) 和 \(C\),那么可以得到 \((A \oplus B) \oplus C = A \oplus (B \oplus C)\),这表明多个数值连续进行异或计算时,括号的位置不会影响结果。 3. **恒等律** 任何数与零做异或运算都会返回该数本身,即 \(A \oplus 0 = A\)。这是因为零的所有位均为 `0`,而按照异或定义,当其中一个操作数为 `0` 时,结果等于另一个操作数。 4. **自反性/逆元特性** 当一个数与其自身相异或时,结果总是 `0`,表达式形式为 \(A \oplus A = 0\)。这是由于每一位上相同的值会相互抵消。 5. **幂等性缺失** 虽然某些其他逻辑运算可能具备幂等性(比如 AND 或 OR),但是 XOR 不满足这一属性——重复施加同一个输入并不会保持原样不变而是变为相反状态或者归零。 ### 异或运算的应用场景 基于上述提到的独特性质异或广泛应用于多种领域和技术实现当中: - **数据加密解密** 利用异或不可预测性和可逆特点,在密码学里经常作为基础算法之一来构建简单的流加密方案。例如通过固定密钥对明文逐比特实施一次一密技术即可完成初步保护措施[^2]。 - **错误检测机制** 在通信协议设计过程中采用奇偶校验方法时也会涉及到异或概念;发送端先统计有效载荷里面含有多少个‘1’再附加额外标志位使得整体数量成为期望模式(单数还是双数取决于具体需求), 接收方收到消息后再重新验证一遍从而判断传输期间是否存在误码现象发生. - **快速查找丢失重复项等问题解决策略** 借助于自我消除特性的优势, 可以巧妙地处理数组中寻找唯一元素之类的挑战型题目. ```python def find_unique_element(nums): result = 0 for num in nums: result ^= num return result ``` 此函数利用了异或的自反性原理,遍历列表中的每一个数字并累积它们之间的异或值,最后剩下的那个未被配对的就是我们要找的目标独特值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值