跳转至

0102 —— a ^ b ^ b == a (Tsoding)

元旦期间,没有出门玩。一是天气太冷零度左右,二是单身优势hhh。所以无聊刷b站,经常刷到Tsoding的视频,但平时对这类大佬编程视频只是看个表面(纯键盘输入,emacs编辑无补全等等)没有深入了解内容,可能确实是太无聊了,发现了一些有意思的东西,所以记录下来。

两次按位异或 结果不变

a       = 0011 1100
b       = 0000 1101

a^b     = 0011 0001
a^b^b   = 0011 1100

这个炫酷的小性质可以有很多的运用,例如最基本的加密算法、不占用额外空间交换两个变量值、线性时间内找出重复元素等等。

基础加密与密钥

既然两次异或运算,结果不变。

可以设置一个运算值k(密钥),用k进行一次异或运算加密,再用k进行一次异或运算解密

以字符串举例,我们列出每个字符的ascii值

str = 'hello,world'

[ord(a) for a in str]

# [104, 101, 108, 108, 111, 44, 119, 111, 114, 108, 100]

再对每个ascii值进行异或运算加密

k = 12

[ord(a)^k for a in str]
# [100, 105, 96, 96, 99, 32, 123, 99, 126, 96, 104]

[chr(ord(a)^k) for a in str]
# ['d', 'i', '`', '`', 'c', ' ', '{', 'c', '~', '`', 'h']

''.join([chr(ord(a)^k) for a in str])
# 'di``c {c~`h'

我们获得了str的加密字符串。对加密字符串使用密钥解密

def encrypt(str,k): return''.join([chr(ord(a)^k) for a in str])

encode_str = encrypt(str,12)
# 'di``c {c~`h'

encrypt(encode_str,10)
# 'ncjji*qitjb' 密钥错误

encrypt(encode_str,12)
# 'hello,world' 密钥正确

这是一个最基础的使用密钥加密解密的例子,这容易被频率分析等手法破解,使用只是示例使用

交换两个变量值

通常我们交换两个变量值a,b。要开设另外一个变量空间c,用于交换。

c = a保存,a = b赋值,b = c赋值。

在这个技巧中,我们可以让a,b交换,而不使用额外空间

int main()
{
    int a = 69;
    int b = 420;
    printf("%d %d\n",a,b);
    a ^= b;// a = 69^420 b = 420
    b ^= a;// a = 69^420 b = 420^69^420 = 69 
    a ^= b;// a = 69^420^69 = 420 b = 69 
    printf("%d %d\n",a,b);
    return 0;
}