跳到主要内容

格雷码完全指南:相邻只变一位,二进制与格雷码怎么互转

讲清楚格雷码为什么相邻两数只差一个比特位,二进制异或转格雷码的公式怎么来的,以及它在旋转编码器、卡诺图和抗干扰场景里的真实用途。

发布于 作者 李雷
#格雷码 #二进制 #编码器 #卡诺图

格雷码完全指南:相邻只变一位,二进制与格雷码怎么互转

普通二进制计数有个让硬件工程师头疼的毛病:从 3(011)跳到 4(100),三个比特位同一瞬间全翻了。如果读取电路恰好在翻转中途采样,它可能锁到 111 或 000 这种离谱的中间值。格雷码就是为了堵住这个漏洞而生的,它的核心承诺只有一句话,任意两个相邻的值只相差 1 个比特位。

格雷码的核心性质:相邻只变一位

先把 0 到 7 用普通二进制和格雷码并排列出来,差别一眼就看清了。

| 十进制 | 普通二进制 | 格雷码 | |---|---|---| | 0 | 000 | 000 | | 1 | 001 | 001 | | 2 | 010 | 011 | | 3 | 011 | 010 | | 4 | 100 | 110 | | 5 | 101 | 111 | | 6 | 110 | 101 | | 7 | 111 | 100 |

顺着格雷码这一列往下读,000 到 001 变了最后一位,001 到 011 变了中间一位,011 到 010 又变回最后一位。每一步,有且只有一个数字翻转。普通二进制那一列做不到,2 到 3 还好,3 到 4 就一次性翻了三位。这个差别看似不起眼,在物理世界里却是误差能不能钻进来的分水岭。

二进制怎么异或转成格雷码

把一个数转成格雷码,公式短到可以背下来:gray = n ^ (n >> 1)。意思是这个数和它右移一位之后的结果做一次按位异或。

拿 5 走一遍。5 的二进制是 101,右移一位得到 010。两者逐位异或:最高位 1 异或 0 得 1,中间位 0 异或 1 得 1,最低位 1 异或 0 得 1,结果是 111。所以 5 的格雷码是 111,也就是十进制 7。

再看题目要的那个例子,二进制 0110(十进制 6)。右移一位是 0011,0110 异或 0011 逐位算:0、1、0、1,得到 0101。所以二进制 0110 的格雷码是 0101。这个数对照上面的表也能验证,6 那一行格雷码正是 101,补齐四位就是 0101。

为什么异或就能保证相邻只变一位?因为相邻两个数的二进制表示,差别只在某一段连续的低位翻转。异或上自己右移一位的版本,等于让每一位记录"我和我左边那一位是否相同"。相邻数变化时,这种"相邻位比较"的结果只会在一个位置上发生改变,于是输出就只动一位。

格雷码怎么解码回二进制

很多人栽在这里:以为解码就是把编码公式倒着用一遍。不是的。编码是一次移位加一次异或,解码却要把每一位和它更高的所有位做异或。

具体做法是从最高位往下扫:最高位直接抄下来,之后每一位等于格雷码当前位异或上已经解出的上一位结果。拿 111 解回去,最高位 1 照抄,第二位 1 异或 1 得 0,第三位 1 异或 0 得 1,解出 101,正是十进制 5,和编码时往返完全对得上。如果你图省事用编码公式去解码,任何大于 1 的值都会出错,这是写格雷码程序时最常见的一个坑。

它到底用在哪里

我第一次真正理解格雷码的价值,是在调一个绝对式旋转编码器的时候。码盘上的刻线如果按普通二进制排布,读取头扫过 0111 和 1000 这种交界处时,四条光栅不可能严丝合缝地同时切换,读出来的位置会瞬间乱跳。换成格雷码刻线后,相邻位置只差一位,读取头哪怕稍微对不齐,报出来的位置最多偏一格,绝不会出现离谱的大跳变。那一刻我才明白,这不是数学上的小聪明,而是实打实省掉了一层硬件滤波。

除了编码器,格雷码还撑起了卡诺图。卡诺图能用来化简布尔表达式,前提就是行头和列头按格雷码排列,相邻格子只差一个变量,这样相邻的 1 才能干净地圈在一起。此外它还出现在纠错编码、遗传算法的基因编码,以及一些模数转换器里。规律很统一:只要"一位错位"的代价比"多位同时跳变"更小,格雷码就有它的位置。

动手试一遍

理解一个编码最快的方式就是亲手转几个数。打开 格雷码转换器,填 5 看它返回 111,填二进制 0110 看它返回 0101,再把行数调大,顺着教学对照表逐行确认每个相邻项都只翻一个数字。想顺带复习二进制、八进制、十六进制之间的换算,可以配合 进制转换器 一起用,把格雷码和它对应的普通二进制摆在一起对照,异或那一步发生了什么就看得更透了。

格雷码不复杂,核心就一条:相邻只变一位,代价是顺序不再是直觉里的连续递增。理解了 gray = n ^ (n >> 1) 这个公式和它背后的"相邻位比较",你就抓住了它的全部精髓。


Made by Toolora · Updated 2026-06-13