自异或性质笔记
自异或简述
自异或指的是一系列数值本身与自身进行异或的算法,例如存在 \[ A\oplus A=0 \] 也算是一种算法。
但本文只讨论一些需要推理过程的自异或逆算法。
自位移异或
自位移异或指的是形如 \[ A\oplus (A>>bit) \] 的算法。
简单起见,我们观察一个 8 位二进制数,右移 3 位后异或的过程。
1 | value: 1101 0010 |
首先,观察到 result
的最高 shift
位与
value
的最高 shift
位是一样的。因此,在
result
的基础上,我们可以将其与一个二进制遮罩取与,得到
value
的最高 shift
位。这个遮罩应该是:1111 1111 << (8 - 3) = 1110 0000
。于是我们得到
1100 0000
。
其次,注意到对于异或运算有如下事实:a ^ b ^ b = a
。依靠二进制遮罩,我们已经获得了
value
的最高 shift
位。因此,我们也就能得到
shifted
的最高 2 * shift
位。它应该是
1100 0000 >> 3 = 0001 1000
。将其与
result
取异或,则能得到 value
的最高
2 * shift
位。于是我们得到 1101 0000
。
我们很容易可以发现,最多只需要进行这样的操作两次即可还原原本的值。
我们同样对其他位数的二进制数进行取样,可以很容易发现,操作次数与位数的关系是: \[ times=bits/shift \] 同理,对于左位移异或也是一样的,但是需要注意的是,一般来说左位移异或会给予一个掩码值确保左异或不会越界,所以写出完整的自位移异或逆算法如下:
1 | def unshiftRight(x: int, shift: int, mask: int = None, bits: int = 32): |