✦ 当然,格雷码(Gray Code),又称为反射二进制码(Reflected Binary Code),是一种非常巧妙的二进制编码系统。

核心特点

它最显著的特点是:任意两个连续的代码之间,只有一位(bit)不相同。

这与我们常用的标准二进制码(Natural Binary Code)有很大区别。例如,在标准二进制码中,从 7 转换到 8(0111 -> 1000),有四位同时发生了变化。

对比示例

下面是 0 到 7 的标准二进制码和格雷码的对比,你可以清晰地看到格雷码的“单位距离”特性:

┌────────┬──────────────┬────────┬──────────────┐ │ 十进制 │ 标准二进制码 │ 格雷码 │ 格雷码变化位 │ ├────────┼──────────────┼────────┼──────────────┤ │ 0 │ 000 │ 000 │ │ │ 1 │ 001 │ 001 │ (第0位变化) │ │ 2 │ 010 │ 011 │ (第1位变化) │ │ 3 │ 011 │ 010 │ (第0位变化) │ │ 4 │ 100 │ 110 │ (第2位变化) │ │ 5 │ 101 │ 111 │ (第0位变化) │ │ 6 │ 110 │ 101 │ (第1位变化) │ │ 7 │ 111 │ 100 │ (第0位变化) │ └────────┴──────────────┴────────┴──────────────┘

为什么使用格雷码?

格雷码的主要优点是可靠性和抗干扰性。

想象一个旋转编码器,它用光感应器读取盘上的二进制码来确定角度。如果使用标准二进制码,当盘片从位置 3 (011) 转到位置 4 (100) 时,三位都需要同时改变。但在物理世界中,这种改变不可能绝对同步发生。

  • 如果第2位先变:011 -> 111 (瞬间读成 7)
  • 如果第0、1位先变:011 -> 000 (瞬间读成 0)

这种瞬间的巨大读数错误在很多系统中是致命的。而如果使用格雷码,从 3 (010) 转到 4 (110),只有一位发生变化,无论何时读取,读数要么是旧值 010,要么是新值 110,绝不会出现中间的巨大跳变错误。

生成方法(镜像法)

格雷码的生成非常有规律,可以用镜像反射法来构造:

  1. 1位格雷码:

1 0 2 1 2. 2位格雷码: * 将1位格雷码列表镜像反转:1, 0 * 在原列表前加0,在镜像列表前加1:

1 00 (原列表+0) 2 01 3 -- (镜像线) 4 11 (镜像列表+1) 5 10 3. 3位格雷码: * 将2位格雷码列表 00, 01, 11, 10 镜像反转:10, 11, 01, 00 * 在原列表前加0,在镜像列表前加1:

1 000 2 001 3 011 4 010 5 --- 6 110 7 111 8 101 9 100 这个过程可以无限重复,生成任意位数的格雷码。

转换算法

  1. 二进制码转格雷码 方法:二进制码的最高位保持不变,其余各位是该位与前一位二进制码进行异或(XOR)运算的结果。 公式:Gray = Binary XOR (Binary >> 1) (其中 >> 是右移一位)

示例:将二进制 10110 转换为格雷码。

  • G4 = B4 = 1
  • G3 = B4 XOR B3 = 1 XOR 0 = 1
  • G2 = B3 XOR B2 = 0 XOR 1 = 1
  • G1 = B2 XOR B1 = 1 XOR 1 = 0
  • G0 = B1 XOR B0 = 1 XOR 0 = 1 结果:格雷码为 11101。
  1. 格雷码转二进制码 方法:格雷码的最高位转为二进制码的最高位,二进制码的下一位由已转换出的二进制位与下一位格雷码进行异或(XOR)运算得到。

示例:将格雷码 11101 转换为二进制码。

  • B4 = G4 = 1
  • B3 = B4 XOR G3 = 1 XOR 1 = 0
  • B2 = B3 XOR G2 = 0 XOR 1 = 1
  • B1 = B2 XOR G1 = 1 XOR 0 = 1
  • B0 = B1 XOR G0 = 1 XOR 1 = 0 结果:二进制码为 10110。

主要应用领域

  • 旋转/线性编码器:最经典的应用,用于测量角度和位移。
  • 卡诺图(Karnaugh Map):在逻辑电路化简中,卡诺图的行和列就是按格雷码顺序排列的,确保相邻的方格只有一个变量不同,便于合并化简。
  • 数字通信:用于某些类型的模数转换器(ADC)和数据传输中,以减少状态转换时可能出现的错误。
  • 遗传算法:在一些遗传算法中,使用格雷码对参数进行编码,可以使相邻的数值在基因型(二进制串)上也相邻,便于局部搜索。