我最近遇到了格雷码,我一直试图绕过用于将格雷码转换回二进制(32位或更少)的高效算法。
mask == 0
这是我正在谈论的代码。现在我的问题是:
num = num ^ (num >> 1);
num = num ^ (num >> 2);
num = num ^ (num >> 4);
num = num ^ (num >> 8);
num = num ^ (num >> 16);
)?如果我们反向执行它会有什么区别:
@{{ }}
我试过这个,似乎产生了相同的结果。
答案 0 :(得分:4)
例如,以位(让' s取8)
h g^h f^g e^f d^e c^d b^c a^b
那么如果我们申请x ^= x >> 1
会怎样?我们得到了这个
h g f^h e^g d^f c^e b^d a^c
这看起来就像我们开始的那样,只是由x ^ (x >> 2)
而不是x ^ (x >> 1)
制作,所以同样的想法只能以2的移位来反转:
h g f e d^h c^g b^f a^e
看起来不错,现在很明显为什么x ^= x >> 4
会完全恢复正常。对于更多位,相同的模式会持续一段时间。
另一种看待这种情况的方法是暂时颠倒这些位,将"变为灰色"进入x ⊗ 3
⊗
乘以GF(2 k ),奇数乘法在GF(2 k )中是可逆的并且是乘法的3的倒数是"所有位设置",您可以按如下方式找到:
y=3
和临时反i=1
y
中的第一位(不是lsb),将相应位设置为反向y=1
所以第一步是y=3, i=1
,y=5, i=3
,y=9, i=7
等等,直到您设置i
中的所有位,然后调用最终i
{{1 }}
然后我们有inv
乘以"所有位设置"意味着每个位最终都是自身的XOR和所有低位,您可以使用
(x ⊗ 3) ⊗ inv = x ⊗ (3 ⊗ inv) = x ⊗ 1 = x
首先,所有位都被它们旁边的位进行异或,然后是两个下一位(它们已经被异或,所以这只需要一步),然后是接下来的四位等。
再次反转这些位以获得你的开始。
但现在是有趣的东西。
(是的,实际上你不仅可以撤销这些步骤,而且可以任意改变它们)
好的,反转这些位然后返回GF(2 k )。另一种写每一行的方法是
x ^= x << 1
x ^= x << 2
x ^= x << 4
...
最终结果当然是x = x ⊗ 3
x = x ⊗ 5
x = x ⊗ 17
...
GF中的乘法(2 k )是非常好的和可交换的,所以它可以按任何顺序完成。
当然,只要他们的产品是((x ⊗ 3) ⊗ 5) ⊗ 17 = x ⊗ (3 ⊗ 5 ⊗ 17) = x ⊗ 127
。但是所有其他选择都会导致烦人/许多被乘数出现。例如,我们可能希望9是一个因子,然后其余的是199,它可以分解为9⊗63,依此类推,但这会持续一段时间,直到你可能有3,5,9,9,17, 65并且这很糟糕(并注意到9⊗9⊗65 = 1,如果有8位,那么是的,只是踢出来并回到原来的3,5,17)。但是可能。