异或的性质
异或(xor)是一种二进制运算,简单的记,就是对应数位相异为1.
0 | 1 | |
---|---|---|
0 | 0 | 1 |
1 | 1 | 0 |
异或满足如下性质(此处用^表示异或符号):
交换律: A ^ B = B ^ A
结合律: (A ^ B) ^ C = A ^ (B ^ C)
一个二进制数与0异或还是自身: A ^ 0 = A
一个二进制数与自身异或是0: A ^ A = 0
推论性质:
一个数与另一个数异或2次还是自身,即 A ^ B ^ B = A
证明:
A ^ B ^ B = A ^ (B ^ B) = A ^ 0 = A
异或的这些性质有很多有趣的应用:
1. 不用临时变量交换2个数字
let a = 10, b = 20
a = a ^ b
b = a ^ b = (a ^ b) ^ b = a
a = a ^ b = (a ^ b) ^ a = b
console.log(a, b) // 20, 10
2. 检查出现偶数次的数字或出现奇数次的数字。例如下面一列数字都是成对出现的,里面只有一个数字出现了1次,如何找到这个数字?
let numbers = [2, 5, 7, 9, 11, 11, 9, 2, 7]
numbers.reduce((a, b) => a ^ b) // 5
原理就是上面说的性质,所有数字的异或,通过交换律和结合律,会变成如下的形式:
(a ^ a) ^ (b ^ b) ^ ... ^ x = 0 ^ 0 ^ ... ^ x = x
3. 数据校验,可以通过将数据逐位异或,来生成一个校验和,来检测数据传输或存储中的错误
function validationCode(txt) {
return Array.from(txt)
.map(c => c.charCodeAt(0))
.reduce((a,b) => a ^ b);
}
let hello = "hello,world";
let hello2 = "hello,world";
console.log(hello, validationCode(hello));
console.log(hello2, validationCode(hello2));
// hello,world 44
// hello,world 65292