格雷码
格雷码(Gray code)是把一组离散状态排列成序列,使相邻状态只在一个位置发生变化的编码方式。最常见的是二进制格雷码:它列出全部 位二进制字,每个出现一次,相邻字的汉明距离为一。若首尾也只差一位,称为循环格雷码。
普通二进制计数从 变到 ,三位都发生变化;一种三位格雷码则按 排列。每步只翻一位,最后的 也只需翻最高位便回到 。这使它适合按单个开关变更状态、增量枚举子集等场景;它本身并不是纠错码。
汉明距离与超立方体
两个长度相同的二进制字的汉明距离,是不同位置的个数。例如 ,。把全部 位字作为顶点,只连接汉明距离为一的两个字,得到 维超立方体图 。
因此,列出全部状态的格雷码对应这张图中经过每个顶点恰一次的路径;当 时,循环格雷码对应首尾也相连的环。 的序列 仍满足循环相邻字只差一位,但 只有一条边,不构成简单图中的环。这个图论解释约束的是状态的先后关系,不表示二进制数值的大小顺序。[1]
反射构造与完整归纳证明
二进制反射格雷码从 开始。已有 时,先按原顺序给所有字添加前缀零,再按反序给它们添加前缀一: 例如 。构造 时,前半段是 ,后半段是倒过来的 。
证明。 假设 已包含每个低 位字恰一次,且相邻字只差一位。新序列前、后两半的最高位不同,因此互不重复;每一半的低位又穷尽全部可能字,合起来恰有全部 个状态。
在同一半内部,最高位固定,低位沿旧序列或其反序移动,仍只差一位。两半的交界处,低位都是旧序列的最后一个字,只改变新添加的最高位。新序列的最后一个字与第一个字,低位也都等于旧序列的第一个字,仍只差最高位。基础 可直接检查,因此对所有 都得到循环格雷码。
直接编码与解码
把整数 的普通二进制字记为 。反射码在第 个位置的字为 其中 是逐位异或:两位相同得零,不同得一。逐位表达为 最高位先确定,其余每位比较普通二进制相邻两位,便得到格雷字。这个关系与前述反射递推一致:最高位固定为零时沿旧顺序,高位由零变一后低位的顺序反转。
还可直接证明相邻字只差一位。若 末尾恰有 个连续的一,则从 加一时,最低 位翻转,即 因此 结果只有第 位为一,证明相邻格雷字确实只差这一位。这里相邻索引取 ;首尾关系由 单独核对。
解码可从最高位向下恢复: 例如 ,先得最高位一,接着得 ,最后得 ,所以普通二进制为 ,即索引六。每一位都被唯一恢复,也证明直接编码是双射。
Python 实现
以下函数生成反射格雷码的字符串列表,位数为正整数;另一个函数把非负格雷整数解回普通整数。返回的列表包含全部状态,不依赖全局可变数据。
def gray_words(bits):
if type(bits) is not int or bits < 1:
raise ValueError("bits must be a positive integer")
return [format(i ^ (i >> 1), f"0{bits}b")
for i in range(1 << bits)]
def gray_to_integer(gray):
if type(gray) is not int or gray < 0:
raise ValueError("gray must be a nonnegative integer")
result = 0
while gray:
result ^= gray
gray >>= 1
return result
print(gray_words(3))
print(gray_to_integer(0b101))
# ['000', '001', '011', '010', '110', '111', '101', '100']
# 6
解码中的逐次异或,将格雷字与其右移一位、两位等的结果叠加。每个输出位得到相应高位格雷位的异或前缀,恰好实现上述递推。生成字符串列表至少需输出 个字符,所以时间和结果空间均为 ;不能因为直接编码只有一条异或表达式,就把枚举全部状态说成常数时间。解码循环运行至多字的位数次;若按大整数位操作计成本,还要计入每次异或和移位涉及的位长。
变式。 两位输出是 ,最后回到开头只翻最高位。一位输出是 ;零位只有一个空字,无法满足“相邻状态恰差一位”的同一循环定义,因此本实现要求正位数。
单位变化与纠错的区别
把 位字看作一个子集的指示向量,格雷顺序每步只增加或删除一个元素。例如三位 只删除最低位对应元素;若维护子集元素权重之和,每步可以只加减一个权重,而不用重新扫描全部元素。
但格雷码仍使用全部 个字,最小距离为一。把某一位读错,结果可能恰好是另一个合法字,编码本身无法保证检测或纠正错误。位置编码器可借它减轻相邻位置交界时多位同时变化的歧义,但电气抖动、采样时序和跨越多个位置仍需另行处理。数学上的单比特邻接条件不是对真实传感系统无误差的承诺。
参考资料
- ↑ Pavel Tvrdík:Embeddings and simulations of INs I+II,CS838,1999,“Embeddings of paths and cycles”中的 Gray sequence、binary reflected Gray code 递推式与逐位代数公式。访问日期:2026年10月25日。