不使用任何外部计数器或其他状态,我正在寻找一个高效的函数,它接受一个n位值(大约32位)并返回格雷码中的下一个值。
也就是说:
int fn(int x)
{
int y = gray_to_binary(x);
y = y + 1;
return binary_to_gray(y);
}
尽管binary_to_gray()
函数很简单(x ^ (x >> 1)
),但相应的gray_to_binary()
却不那么简单(需要进行log(n)
次迭代)。
也许有一种更有效的操作序列?无论是对于标准的反射格雷码,还是选择适合该问题的其他格雷码。
附言:我看到这个问题有两种可能的解决方法——一种是选择一种更容易转换为二进制并使用上述给定形式的代码(或演示反射码更有效的转换为二进制的方法),另一种是完全推迟转换为二进制,并生成一种在不使用二进制增量的情况下遍历格雷码的方法。
在后一种情况下,将结果代码转换为二进制可能会变得特别困难。从实际角度来看,这可能是一个缺点,但仍然是一个有趣的事情。
更新:由于已经指出格雷解码仅需要log(n)
次操作(使用两种不同的技术都可以实现),因此我花了一些时间试图弄清楚这是否是简化程度的严格限制。在确定要执行的下一个操作时,必须考虑所有位,否则“考虑”的位将无法更改,函数将在两个值之间振荡。输入必须以某种方式压缩到可管理的比例,以确定要执行的下一个操作。
为了使其成为log(n-k)
操作,可以使用2k-entry LUT来快捷地处理最后的k
个操作(一条评论建议使用k=32
)。
另一种我想到的技术是乘法和位掩码的组合,这通常可以很快地简化事情。例如,计算奇偶校验以实现基于奇偶性的算法。
从乘法和位掩码的方法来看,似乎有空间发明一种进一步简化操作集的格雷码......但我想没有这样的代码是已知的。
log(n)
步骤,而不是n
步。例如:x ^= x >> 1; x ^= x >> 2; x ^= x >> 4; x ^= x >> 8;
等。 - haroldint [2 ^ 32] gray2binary
,其中使用grayCode作为索引,并将二进制代码作为数组条目的值。 ;-) - MrSmith42