IT科技

异或运算常见的应用

时间:2010-12-5 17:23:32  作者:IT科技类资讯   来源:IT科技类资讯  查看:  评论:0
内容摘要:大家可能比较熟悉 "与" 运算 和 "或" 运算 ,相对而言, "异或" 运算 平常使用较少,存在感也不强,如果不是刻意提起,可能还想不到它其实,"异或" 运算也非常重要,它在加密、备份、算法等方面都

大家可能比较熟悉 "与" 运算 和 "或" 运算 ,异或运算用相对而言,异或运算用 "异或" 运算 平常使用较少,异或运算用存在感也不强,异或运算用如果不是异或运算用刻意提起,可能还想不到它

其实,异或运算用"异或" 运算也非常重要,异或运算用它在加密、异或运算用备份、异或运算用算法等方面都有应用,异或运算用每一位开发的异或运算用同学都应该花点儿时间掌握它的特点和规律,以便在日常工作中能灵活的异或运算用运用

接下来将介绍异或运算的一些基础知识以及在实际中的一些应用

基础知识

异或是计算机中一种二元逻辑运算, 运算符号是异或运算用 ^,它按照二进制位进行异或运算,异或运算用结果为 真 或 假,异或运算用 它的运算法则如下

x y x^y 0 0 0 0 1 1 1 0 1 1 1 0

表格 第一列 和 第二列 是异或运算的两个操作数,第三列是异或运算的结果,1 表示真,0 表示假

由表格可知:如果参与运算的两个二进制位相同,则结果为 0 ,亿华云计算否则为 1

也就是说,异或主要用来判断两个值是否相同

重要的性质

下面列出异或运算一些重要的性质,1 表示真,0 表示假, 具体的验证过程比较简单,这里就省略了

1、一个数与自身异或,总是为 0

x ^ x = 0 

2、 一个数与 0 异或,总是其自身

x ^ 0 = x 

3、 交换性

x ^ y = y ^ x 

4、 结合性

x ^ ( y ^ z ) = ( x ^ y ) ^ z 

常见应用

异或运算本身比较简单,重点还是在应用层面,上面列出的性质,在很多方面都有应用

判断两个数是否相等

一个数与自身异或,总是为 0,我们可以使用这一点来判断两个变量是否相等

( a ^ b ) == 0 

当 a 和 b 相等时,表达式为真,否则为假

不使用临时变量交换两个数的值

要交换两个数的值,源码库通常做法是借助一个临时变量,然后再进行交换,比如:tmp 是临时变量,现需要交换 a 和 b 两个变量值,过程如下

tmp = a a = b b = tmp; 

利用异或的一些性质,不用临时变量也能实现交换两个数的值,具体过程如下

a = a ^ b b = a ^ b a = a ^ b 

假如初始时,a = 1、b = 2

第一个等式 a = a ^ b 结果是 a = 1 ^ 2 = 3

紧接着第二个等式 b = a ^ b 结果是 b = 1 ^ 2 ^ 2 = 1 ^ 0 = 1

最后一个等式 a = a ^ b 结果是 b = 1 ^ 2 ^ 1 = 1 ^ 1 ^ 2 = 0 ^ 2 = 2

可以看到,最终 a = 2、 b = 1 ,它们的值实现了交换

上面的三条语句还可以进一步优化成一条,结果如下

a ^= b ^= a ^= b  简化表达式

根据交换性,可以优化表达式中重复变量的异或运算,比如:表达式 a ^ b ^ c ^ a ^ b 可以做如下简化

a  ^  b  ^  c  ^  a  ^  b                   # 根据 x ^ y  = y ^ x =  ( a  ^  a )  ^  ( b  ^  b )  ^  c        # 根据 x  ^ x = 0 =  0  ^  0  ^  c                            # 根据 x ^ 0 = x = c  加密

利用异或运算加密是很常见的加密手段,它涉及到三个变量:明文、密钥、密文,假如它们分别记为 plain_text、 encrypt_key、 cipher_text

明文和密钥进行异或运算,服务器租用可以得到密文

plain_text ^ encrypt_key = cipher_text 

密文和密钥进行异或运算,可以得到明文

cipher_text ^ encrypt_key  = ( plain_text  ^  encrypt_key ) ^ encrypt_key = plain_text  ^ ( encrypt_key ^ encrypt_key )   # 根据 x ^ ( y ^ z ) = ( x ^ z ) ^ y = plain_text  ^  0                              # 根据 x ^ x = 0 = plain_text  备份

根据异或的性质,异或运算还可以用于文件的备份

现有两个文件 filea 和 fileb,它们进行异或运算,会产生一个新的备份文件 bakfile

bakfile = filea ^ fileb 

根据异或的性质,可以通过 bakfile 和 filea 得到 fileb,或者通过 bakfile 和 fileb 得到 filea

后面无论是 filea 或 fileb 文件损坏了,只要不是两个文件同时损坏,都可以通过两者中未损坏的文件 和 bakfile 文件,还原得到另一个文件

当 filea 文件损坏了,可以通过 fileb 和 bakfile 进行异或运算得到完好的 filea 文件

fileb  ^  bakfile =  fileb  ^ ( filea  ^  fileb ) =  fileb  ^  filea  ^  fileb        # 根据 x ^ ( y ^ z ) = ( x ^ z ) ^ y =  fileb  ^  fileb  ^  filea        # 根据 x ^ x = 0 =  0  ^ filea                       # 根据 x ^ 0 = x =  filea 

同样,当 fileb 文件损坏了,可以通过 filea 和 bakfile 进行异或运算得到完好的 fileb 文件

f

filea  ^  bakfile =  filea  ^ ( filea  ^  fileb ) =  filea  ^  filea  ^  fileb        # 根据 x ^ ( y ^ z ) = ( x ^ z ) ^ y  =  filea  ^  filea  ^  fileb        # 根据 x ^ x = 0 =  0  ^ fileb                       # 根据 x ^ 0 = x =  fileb 

解算法题

有些算法可以利用异或的思路进行求解,下面列出力扣上的一道算法题来说明,题目如下:

一个长度为 n-1 的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围 0 ~ n-1 之内, 在范围 0 ~ n-1 内的 n 个数字中有且只有一个数字不在该数组中,请找出这个数字 示例 1: 输入: [ 0,1,3 ] 输出: 2 示例 2: 输入: [ 0,1,2,3,4,5,6,7,9 ] 输出: 8 

最快捷的解决方法是把数组的所有元素以及 0 到 n-1 之间的整数 全部进行异或运算

arry[0] ^ arry[1] ^ arry[2] ... ^ arry[n-2] ^ 0 ^ 1 ^ 2 .... ^ (n-1) 

由于数组元素值范围在 0 到 n-1,且所有元素值都没有重复

所以,上述的计算式子中,0 到 n-1 每个数会出现两次,只有缺少的那个数仅出现一次,根据异或的性质 x ^ x = 0 可知,相同值之间的异或运算等于 0,因此算式的结果其实就是缺少的那个数

下面给出测试文件 test.cpp,代码是用 C++ 实现的,可以自行用其他语言实现

#include <stdint.h> #include <iostream> using namespace std; int32_t find_missing(int32_t *ary, int32_t len) {      //数组长度小于等于1,直接返回 -1     if(len <= 1)     {          return -1;     }     //结果     int32_t result = 0;     //result 和 数组中每一个元素值进行异或运算     for (int32_t i = 0; i < len; i++)     {          result ^= ary[i];     }     //result 和 0 到 n 中每一个值进行异或运算     for (int32_t j = 0; j <= len; j++)     {          result ^= j;     }     return result; } //编译: g++ -g -o test  test.cpp int32_t main(int32_t argc , char *argv[]) {      int32_t ary[] = {  0, 1, 3 };     int32_t result = find_missing(ary, sizeof(ary) / sizeof(int32_t));     std::cout << "result = " << result << std::endl;     return 0; } 

使用 g++ -g -o test test.cpp 命令编译,接着运行程序,结果如下:

[root@localhost test]# ./test  result = 2 

当然,这道题目还有其他的解法,比如:利用加法来解,大家自己去思考下,这里不做介绍了

题目链接 https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof/

小结

通过上文,我们可以看到,异或运算在很多方面都有应用,其实,它的应用远不止文中介绍的方面,所以,我们花时间去掌握它是非常值得做的一件事

copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap