在“青云仓”快递分拣中心,三位老师傅各有一套独门编码手艺。仓管老王负责给货箱贴标签,他把一个两位数拆成两个单独的数字,每个数字用 4 格小标签编码,分拣员一眼就能读回十进制——这就是 BCD 码。电梯维修工小李发现,楼层从 3 到 4 切换时多位指示灯同时闪烁会造成瞬间乱码,于是他重新设计按钮编码,让相邻楼层只变化一个灯——这就是格雷码。质检员小张在每个包裹上额外贴一张“1 的个数奇偶”的核对贴纸,收货方数一数 1 的个数,就能知道运输途中数据是否被篡改——这就是奇偶校验码。三种编码分别回答了数字世界的三个根本问题:十进制数字如何在二进制世界中被直观表达?状态切换时如何把误读风险降到最低?数据被噪声破坏时如何用最小代价发现异常?本文用这个故事带你理解这三种编码的原理与应用。

岗位关联

对 AI 从业者而言,这些底层编码是读懂芯片数据手册、调试通信协议、设计数据采集管线的基本功——你的模型再好,硬件层读错一个 bit,整个推理链都会崩塌。

目录
  1. 可视化演示
  2. BCD码基础
  3. BCD码运算与转换
  4. 格雷码原理
  5. 格雷码典型应用
  6. 奇偶校验原理
  7. 校验局限与改进
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

BCD码基础

青云仓里最繁忙的就是仓管老王。他的工作台前摆着一排排纸箱格子,每个格子固定有 4 个小窗口,窗口上方印着 8、4、2、1 四个数字。老王要标记“47 号货箱”时,他不会费劲把 47 整个换算成二进制,而是把 47 拆成“4”和“7”两个字,分别放进高位格和低位格。在“4”的格子里,他点亮权重 4 的那扇窗;在“7”的格子里,他点亮权重 4、2、1 的三扇窗。分拣员路过一看,立刻读出“四十七”,完全不需要心算二进制。

这套“每位十进制数字单独用 4 位二进制编码”的方法,就是 BCD 码(Binary-Coded Decimal,二进制编码的十进制数)。因为最常用的 4 位权重是 8、4、2、1,所以它又叫 8421 码。4 位二进制本来能表示 0 到 15 共 16 个状态,BCD 码只使用 0 到 9 这 10 个状态,剩下的 1010 到 1111 是“废码”。一旦运算结果落进废码区,就说明出现了错误或需要修正。

老王的标签系统虽然比纯二进制多用了一点纸箱,却让整个分拣链路的可读性大幅提升。BCD 码的工程哲学正是如此:用约 20% 的存储空间冗余,换来十进制显示、电路译码和人类调试的极大便利。

(47)10=(0100 0111)BCD\displaystyle (47)_{10} = (0100\ 0111)_{\text{BCD}}
这个公式表示:十进制 47 被拆成数字 4 和 7,各自编码成 4 位二进制,再拼接起来。组与组之间不是二进制进位关系,而是十进制位的关系。
  1. 拆分十进制位把 47 拆成十位 4 和个位 7,每位单独处理。
    4710→十位 4, 个位 747_{10} \rightarrow \text{十位 } 4,\ \text{个位 } 7
  2. 编码十位 4按权重 8、4、2、1 展开,4 只需用到权重 4 这一位。
    410=0×8+1×4+0×2+0×1=010024_{10} = 0 \times 8 + 1 \times 4 + 0 \times 2 + 0 \times 1 = 0100_2
  3. 编码个位 77 等于权重 4 加 2 加 1,三窗齐亮。
    710=0×8+1×4+1×2+1×1=011127_{10} = 0 \times 8 + 1 \times 4 + 1 \times 2 + 1 \times 1 = 0111_2
  4. 拼接两位按“先高位后低位”的顺序把两组 4 位码连起来。
    (47)10=0100⏟十位 4 0111⏟个位 7(47)_{10} = \underbrace{0100}_{\text{十位 }4}\ \underbrace{0111}_{\text{个位 }7}

BCD码运算与转换

货箱不仅要贴标签,还要合并。老王把 7 号箱和 5 号箱的货物合并成一个新箱,按十进制心算是“7 + 5 = 12”。可标签纸箱每个格子最多认到 9,11、12 这些结果在格子里根本放不下。老王挠头:标签系统自己不会“满十进一”吗?答案是:会,但必须按 BCD 的规矩来。

两个 BCD 数直接按二进制相加时,可能得到大于 9 的结果,或者直接产生进位。因为 BCD 只承认 0 到 9,一旦结果越过 9,就进入废码区,必须进行“加 6 修正”。为什么是加 6?因为 4 位二进制满 16 才进位,而 BCD 满 10 就要进位,中间差了 6。补上这个差,低 4 位就能回到合法区间,同时向更高位正确进位。

老王后来把这条规则写进了仓库手册:任何一位 BCD 相加,超过 9 或产生进位,就当场补 6。这个“人工进位”看起来笨拙,却在所有十进制显示设备里默默运行——电子表、计算器、收银机,都是靠这一补,才让人类看到的数字永远不错位。

7+5:0111+0101=1100 (>9) ⇒ 1100+0110=1 0010 = (0001 0010)BCD\displaystyle 7 + 5:\quad 0111 + 0101 = 1100\ (> 9)\ \Rightarrow\ 1100 + 0110 = 1\ 0010\ =\ (0001\ 0010)_{\text{BCD}}
这条式子是 BCD 加法的灵魂:先用二进制硬加,一旦越界就补 6,把“进错位”纠正为“十进制进位”。
  1. 二进制硬加把 7 的 BCD 码 0111 与 5 的 BCD 码 0101 直接相加。
    01112+01012=11002 (1210)0111_2 + 0101_2 = 1100_2\ (12_{10})
  2. 检查越界结果 1100 大于 BCD 最大合法码 1001(即 9),进入废码区。
    11002>10012 ⇒ 需要修正1100_2 > 1001_2\ \Rightarrow\ \text{需要修正}
  3. 补 6 修正给结果加上 0110(即 6),让低 4 位回到 0 到 9 的范围,同时产生进位。
    11002+01102=1 001021100_2 + 0110_2 = 1\ 0010_2
  4. 解释结果进位 1 作为高一位的“1 个十”,低 4 位 0010 就是数字 2,合起来是 12。
    1 00102→(0001 0010)BCD=12101\ 0010_2 \rightarrow (0001\ 0010)_{\text{BCD}} = 12_{10}

格雷码原理

小李是青云仓的电梯维修工。他修过最诡异的一个故障是:电梯明明从 3 楼到 4 楼,楼层显示屏却会瞬间闪出一个“0 楼”甚至“8 楼”。他蹲在控制柜前一查,发现问题出在编码方式上:二进制从 3(011)到 4(100),三个指示灯同时变化,继电器动作总有先后,中途就会拼出 000(0 楼)、111(8 楼)这样的乱码状态。

小李的解决思路不是让继电器变快,而是换一种编码:让相邻楼层之间永远只变化一位。这种“相邻码距恒为 1”的编码,就是格雷码(Gray Code),由贝尔实验室的 Frank Gray 在 1953 年提出。格雷码构造时像照镜子一样反射:先写 0、1,然后以中间为镜,镜中头部补 0,镜像部分补 1,不断递归生成。3 位格雷码序列是 000、001、011、010、110、111、101、100——每一步确实只翻一位。

小李把电梯按钮全部换成格雷码后,楼层切换瞬间只有一个灯在动,显示屏再也没有闪过“幽灵楼层”。格雷码的启示是:当变化不可能同时发生时,就让变化的内容尽量少——这比任何昂贵的电路优化都更彻底。

G=B⊕(B≫1)即Gi=Bi⊕Bi+1,Gn−1=Bn−1\displaystyle G = B \oplus (B \gg 1) \qquad \text{即} \qquad G_i = B_i \oplus B_{i+1},\quad G_{n-1} = B_{n-1}
格雷码不是查表查出来的,它有严格的位运算公式:把二进制数向右移一位,再和自己逐位异或,就得到格雷码。
  1. 右移一位把二进制数 B 整体向右移一位,最高位补 0,得到 B>>1。
    B=11012,B≫1=01102B = 1101_2,\quad B \gg 1 = 0110_2
  2. 逐位异或相同位取 0,不同位取 1,即 G_i = B_i XOR B_{i+1}。
    G=1101⊕0110=10112G = 1101 \oplus 0110 = 1011_2
  3. 保留最高位最高位 G_{n-1} 直接等于 B_{n-1},不参与异或。
    G3=B3=1G_{3} = B_{3} = 1
  4. 验证相邻性把 0 到 15 全部转换后,任意相邻数字的格雷码只差 1 位。
    3:(0010)→4:(0110)仅第二位变化3:(0010) \rightarrow 4:(0110) \quad \text{仅第二位变化}

格雷码典型应用

小李的维修手册里还有一章:电梯井里的位置传感器。轿厢要在几十米高的井道里精确停靠,靠的是井道顶部的一个旋转码盘。码盘上有 n 圈黑白条纹,光敏元件同时读数。如果码盘用的是普通二进制,轿厢一震动,多个读数同时跳变,控制芯片瞬间读到完全错误的位置,轻则急停,重则冲顶。

格雷码正是为这类场景而生的。把码盘按格雷码顺序刻上条纹,每转过一个扇区,码盘输出只变化一位。即使读数刚好发生在翻转瞬间,最多也只差一格,绝不会跳到毫不相关的角度。现代工业旋转编码器、机器人关节角度传感器、电梯楼层计数器都采用这种方案。在芯片设计里,格雷码还有一个著名用途:异步 FIFO 的读写指针跨时钟域传递时,用格雷码指针可以避免多位同时变化带来的亚稳态采样错误。

小李把 17 位格雷码码盘装进轿厢位置传感器后,电梯运行曲线变得丝滑。格雷码在应用中的真谛是:用“每次只变一点”的代价,换回“任何时刻读数都可信”的确定性。这对高速运动的控制系统而言,比什么都重要。

角度分辨率=360∘2n\displaystyle \text{角度分辨率} = \frac{360^{\circ}}{2^{n}}
n 位格雷码能把一圈分成 2^n 个扇区,每个扇区的角度就是分辨率。位数越多,测角越精细。
  1. 格雷码数量n 位格雷码共有 2^n 个互不相同的码字。
    n=8 ⇒ 28=256 种码字n = 8 \ \Rightarrow\ 2^8 = 256\ \text{种码字}
  2. 划分圆周把 360 度的圆盘按码字数量等分。
    每个扇区角度=360∘256\text{每个扇区角度} = \frac{360^{\circ}}{256}
  3. 计算分辨率相除得到每个扇区对应约 1.4 度。
    360∘256≈1.40625∘\frac{360^{\circ}}{256} \approx 1.40625^{\circ}
  4. 工程含义位数每加 1,分辨率翻倍,码盘条纹密度也翻倍。
    n=17 ⇒ 360∘217≈0.0027∘n = 17 \ \Rightarrow\ \frac{360^{\circ}}{2^{17}} \approx 0.0027^{\circ}

奇偶校验原理

质检员小张站在传送带末端,手里拿着一沓“奇偶贴纸”。他和发货端约定:每个包裹的标签上,“1”的个数加起来必须是偶数。发货前,如果数据位里“1”的个数是奇数,就在末尾的贴纸上写 1;如果是偶数,就写 0。包裹到站,小张只要把所有位(含贴纸位)的“1”数一遍:是偶数,放行;是奇数,立刻拦截。

这就是奇偶校验码(Parity Check Code)的工作方式。它把一个校验位附加在数据之后,使整个码字中“1”的个数满足约定的奇偶性。接收方重新统计 1 的个数,就能发现传输过程中是否发生了奇数个比特翻转——尤其是最常见的单比特翻转。校验位的计算可以用异或极简实现:偶校验时,校验位等于所有数据位的异或结果。

小张的贴纸法虽然只花 1 比特的代价,却是世界上最广泛使用的检错手段。UART 串口通信、PCI 总线、动态存储器的行校验,到处都有它的身影。它回答的问题只有一个——“1 的个数对不对”,但正是这一个问题,挡住了无数次数据被噪声篡改的灾难。

P=bn−1⊕bn−2⊕⋯⊕b0\displaystyle P = b_{n-1} \oplus b_{n-2} \oplus \cdots \oplus b_0
把所有数据位逐位异或:结果为 0 说明“1”的个数是偶数,校验位补 0;结果为 1 说明“1”的个数是奇数,校验位补 1,从而凑成偶校验。
  1. 列出数据位取数据帧的所有比特,例如 1011。
    b3=1, b2=0, b1=1, b0=1b_3 = 1,\ b_2 = 0,\ b_1 = 1,\ b_0 = 1
  2. 逐位异或从高位到低位依次异或,相同为 0,不同为 1。
    1⊕0=1,1⊕1=0,0⊕1=11 \oplus 0 = 1,\quad 1 \oplus 1 = 0,\quad 0 \oplus 1 = 1
  3. 得到校验位最终异或结果是 1,说明数据位有奇数个 1。
    P=1P = 1
  4. 拼接发送把校验位附加在数据末尾,构成新码字 1011|1。
    10112+P=1011121011_2 + P = 10111_2

校验局限与改进

有一天,小张收到一个包裹,奇偶贴纸显示“偶数”,校验通过。可打开一看,有两件货物被调包了。他立刻明白:两件货物同时被换,一个“1”变成“0”、另一个“0”变成“1”,总数奇偶性没变,贴纸自然发现不了。小张感叹:贴纸只能发现“一个或奇数个”问题,遇上“偶数个”差错就彻底失灵了。

这正是奇偶校验的固有局限。它只需 1 位冗余,也只能输出 1 比特的结论“对或错”,因此既无法检测偶数位翻转,也无法定位出错位置,更谈不上纠错。为了对抗更复杂的噪声环境,工程界发展了两类更强的校验技术。海明码(Hamming Code)布置多个校验位,让每个校验位覆盖一组不同位置的比特,不仅能用校验结果组合定位出错的位置,还能实现 1 比特自动纠错。CRC(循环冗余校验)则把一个数据帧看作多项式,用生成多项式做模 2 除法,得到的余数作为校验码,检错能力远强于奇偶校验,以太网和硬盘存储都在使用。

小张后来把防护体系升级成“组合拳”:普通包裹贴奇偶贴纸,贵重包裹走 CRC 装甲,医疗包加海明码医疗兵。三种校验各有定位——轻量、重型、可修复。选择哪种,取决于你要防的是什么样的敌人,以及数据坏了之后,你能不能承担。

2k−1≥n+k\displaystyle 2^{k} - 1 \ge n + k
海明码的设计公式:n 个数据位需要 k 个校验位,要满足 2^k 种组合至少能区分“无错误”加上所有 n+k 个位置。
  1. 统计状态数k 个校验位可以产生 2^k 种组合。
    k=4 ⇒ 24=16 种组合k = 4 \ \Rightarrow\ 2^4 = 16\ \text{种组合}
  2. 位置总数n 个数据位加 k 个校验位,共有 n + k 个比特可能出错。
    n=8, k=4 ⇒ n+k=12n = 8,\ k = 4 \ \Rightarrow\ n + k = 12
  3. 再加无错状态除了“某一位出错”的 n+k 种情况,还要表示“一切正常”这一种。
    2k≥n+k+1 ⇒ 2k−1≥n+k2^k \ge n + k + 1 \ \Rightarrow\ 2^k - 1 \ge n + k
  4. 代入验证8 位数据选 4 个校验位,16 >= 13 成立;3 个校验位则 7 < 12 不够用。
    k=4: 16≥12+1 ✓k=3: 8<12+1 ×k = 4:\ 16 \ge 12 + 1\ \checkmark \qquad k = 3:\ 8 < 12 + 1\ \times

AI 应用场景

嵌入式设备的BCD时间与金额显示

阶段:数据采集与预处理(硬件数据表示与校准)

解决的问题:传统收银、计时设备需要把二进制数转成人类可读的十进制显示,转换电路复杂;使用二进制小数存储金额还会带来 0.1 这类浮点误差,在金融场景中不可接受。

具体案例:智能电子秤的金额计算与显示。单片机直接以 BCD 格式保存单价与重量寄存器,数码管驱动芯片逐位译码点量,金额计算全程无浮点误差;调试时打印寄存器值,工程师一眼就能读出当前金额,无需二次换算。

机器人关节的格雷码角度反馈

阶段:感知与定位(关节角度实时反馈)

解决的问题:机械臂关节在高速运动时,普通二进制编码器的多位输出同时跳变,控制器可能瞬间读到错误角度,导致轨迹规划出现抖动甚至飞车。

具体案例:某六轴协作机械臂采用 17 位光电格雷码编码器,关节角度分辨率达到约 0.0027 度。由于格雷码任意时刻采样最多偏差一个最小步长,视觉伺服模块收到的角度永远“可解释”,机械臂才能完成平滑的力控装配动作。

IoT数据链路的奇偶校验把关

阶段:数据传输与数据清洗(喂给模型前的质量把关)

解决的问题:物联网传感器通过 LoRa/ZigBee 无线链路将数据送到云端,射频噪声会造成零星比特翻转;若不检错,坏数据会直接污染时序数据库,进而误导 AI 模型的训练与预测。

具体案例:某智慧农业大棚项目在每帧温湿度数据尾部附加奇偶校验位,网关先丢弃校验失败的帧,再写入数据湖。实施后坏帧率从 5% 降到 0.1%,后续 LSTM 温度预测模型的预测误差下降了 18%。

Python 演示

python63 行
# -*- coding: utf-8 -*-"""演示 BCD 码, 格雷码, 奇偶校验码的编解码与检错."""  def to_bcd(n):    """十进制整数转 BCD 码, 例如 47 -> '0100 0111'"""    return ' '.join(f"{int(ch):04b}" for ch in str(n))  def bcd_to_int(bcd):    """BCD 码字符串转十进制整数, 例如 '0100 0111' -> 47"""    value = 0    for part in bcd.split():        value = value * 10 + int(part, 2)    return value  def to_gray(n):    """二进制整数转格雷码: G = B ^ (B >> 1)"""    return n ^ (n >> 1)  def from_gray(g):    """格雷码转二进制整数: 逐位异或还原"""    b = 0    while g:        b ^= g        g >>= 1    return b  def parity_bit(bits, even=True):    """按偶校验或奇校验生成 1 位校验位"""    ones = bits.count('1')    return ones % 2 if even else 1 - (ones % 2)  def check_parity(bits_with_parity, even=True):    """验证带校验位的码流是否通过校验"""    total = bits_with_parity.count('1')    return total % 2 == (0 if even else 1)  if __name__ == '__main__':    print('=== 0~15 的三种编码 ===')    for n in range(16):        bin5 = f"{n:05b}"        p = parity_bit(bin5, even=True)        print(f"{n:2d} | BCD:{to_bcd(n)} | 二进制:{bin5} | 格雷码:{to_gray(n):05b} | 偶校验位:{p}")     print()    print('=== 奇偶校验检错演示 ===')    data = '10110'    p = parity_bit(data, even=True)    frame = data + str(p)    print(f'原始帧: {frame} 校验通过? {check_parity(frame, even=True)}')    flipped = frame[:2] + ('1' if frame[2] == '0' else '0') + frame[3:]    print(f'第3位翻转: {flipped} 校验通过? {check_parity(flipped, even=True)}')     print()    print('=== 格雷码往返转换 ===')    for g in [0, 1, 3, 7, 15, 10]:        print(f'格雷码 {g:04b} -> 二进制 {from_gray(g):04b}')
目的:一次性演示 BCD 码、格雷码、奇偶校验码的编码、转换与检错过程,帮助读者把文字公式变成可运行的代码直觉。
  1. return ' '.join(f"{int(ch):04b}" for ch in str(n))把十进制数的每一位字符单独格式化成 4 位二进制,再空格拼接,实现 BCD 编码。
  2. value = value * 10 + int(part, 2)逐个还原 4 位组为十进制位,并按十进制权重累加,实现 BCD 解码。
  3. return n ^ (n >> 1)二进制转格雷码的核心异或公式,与正文公式完全一致。
  4. b ^= g; g >>= 1格雷码转二进制时,反复让当前值与右移后的 g 异或,逐位还原原码。
  5. return ones % 2 if even else 1 - (ones % 2)偶校验时 1 的个数为奇数就补 1;奇校验时正好相反。
  6. flipped = frame[:2] + ('1' if frame[2] == '0' else '0') + frame[3:]人为翻转第 3 位,模拟传输过程中的单比特错误,验证校验函数能否捕获。

常见误区

误区BCD 码和二进制数都是 0/1 串,所以 BCD 码就是把十进制数整个转成二进制。47 的 BCD 码应该就是它的二进制形式 101111。

正解BCD 码是“每位十进制数字”单独转成 4 位二进制,47 要拆成 4 和 7,分别编码为 0100 和 0111,拼接得到 0100 0111。而整个 47 转成二进制才是 101111。两者看似都是 0 和 1,本质完全不同:前者是“十进制位独立编码”,后者是“整个数值按二进制展开”。

为何常见:因为 0 到 9 的 BCD 编码与二进制形式完全一样,初学者很容易以偏概全,以为所有情况都相同。

误区格雷码也是 0 和 1 组成的,肯定可以直接比大小吧?比如 1011 的数值肯定大于 1000。

正解格雷码的码序是为“相邻只变一位”而设计的,它的码值大小与十进制大小没有单调对应关系。4 位格雷码 1000 代表十进制的 15,而 0000 代表 0,前者的二进制数值虽然大,但它们在码序中分别是末端和起点。需要比较大小时必须先把格雷码转回二进制。

为何常见:人看到 0/1 串的第一反应是“这就是二进制数”,而格雷码恰好长着二进制数的样子。

误区加了校验位就万无一失了吧?校验通过就代表数据一定正确,校验失败就代表数据一定坏了。

正解奇偶校验只能检测奇数个比特位翻转。最常见的单比特翻转当然能查到,但如果有两位同时翻转,1 的个数奇偶性不变,校验会漏报。它只适合错误率较低、以单比特错为主的信道。CRC 检错能力更强,海明码还能纠错,它们才是应对恶劣环境的利器。

为何常见:把“能查出常见错误”误解成“能查出所有错误”,忽略了奇偶校验只统计奇偶性这一本质。

误区格雷码和二进制之间的映射是设计好的查表关系,没有公式,只能死记硬背。

正解格雷码有严格的位运算公式。二进制转格雷码是 G = B ^ (B >> 1);格雷码转二进制可以按 B_{n-1} = G_{n-1}、B_i = B_{i+1} ^ G_i 从高位逐位还原。查表只是工程中的查表加速手段,不是唯一方法。

为何常见:教材通常先展示格雷码对照表,再讲反射构造,初学者误以为编码本质就是查表,忽略了其背后的代数规律。

误区4 位二进制能表示 16 个值,BCD 码只用到 10 个,浪费了 6 种状态,这种设计应该被淘汰。

正解BCD 码确实牺牲了约 20% 的编码空间,但换来了三个实际好处:与十进制显示天然对接(数码管译码器可直接驱动)、避免二进制小数在金融计算中的误差、软件调试时可读性极强。电子表、收银机、金融计算器至今仍大量使用。

为何常见:只从信息论压缩率看问题,忽略了工程上“直观、简单、可靠”往往比空间效率更重要。

面试题

Q1. 十进制数字 9 的 8421 BCD 编码是多少?

单选题 · easy

  • A.1001← 正确答案
  • B.1010
  • C.1000
  • D.0110

答案:A。8421 码按权重 8、4、2、1 展开,9 = 8 + 1,对应 1001。1010 是 BCD 中的废码(10 不合法);1000 是 8;0110 是 6。

Q2. 二进制数 1011 对应的 4 位格雷码是?

单选题 · easy

  • A.1101
  • B.1110← 正确答案
  • C.1000
  • D.1111

答案:B。格雷码公式 G = B ^ (B>>1)。B=1011,B>>1=0101,逐位异或得 1110。这与“高位保留、低位与相邻高位异或”的规则一致。

Q3. 数据位 101101 按偶校验生成的校验位是?

单选题 · easy

  • A.校验位为 0(4 个 1)← 正确答案
  • B.校验位为 1(4 个 1)
  • C.校验位为 0(3 个 1)
  • D.校验位为 1(3 个 1)

答案:A。101101 中 1 的个数为 4,是偶数,偶校验要求总 1 数为偶数,所以校验位补 0。若 1 的个数是奇数,则校验位补 1。

Q4. BCD 码加法中,当 4 位结果大于 9 或产生进位时,正确的修正是?

单选题 · mid

  • A.结果加 6 修正← 正确答案
  • B.结果减 6 修正
  • C.结果加 3 修正
  • D.结果加 12 修正

答案:A。BCD 每满 10 进一位,而 4 位二进制满 16 才进位,中间差 6,所以越界时加 0110 即可。例如 7+5=1100,加 6 得 1 0010,代表十进制 12。

Q5. 4 位格雷码 1011 对应的二进制数是?

单选题 · mid

  • A.1011
  • B.1110
  • C.1101← 正确答案
  • D.1001

答案:C。格雷码转二进制从高位开始:B3=1,B2=B3^G2=1^0=1,B1=B2^G1=1^1=0,B0=B1^G0=0^1=1,得到 1101。也可以用循环异或法验证。

Q6. 格雷码最独特的性质是?

单选题 · mid

  • A.相邻码仅一位不同← 正确答案
  • B.所有码距都是二
  • C.只能用于加法运算
  • D.码值大小与二进制一致

答案:A。格雷码的核心定义就是相邻码距为 1,例如 3 位格雷码 010 到 110 只变最高位。它不能直接比较大小,也不是只用于加法,数值顺序与二进制并不一致。

Q7. 关于 BCD 码与纯二进制的比较,正确的是?

单选题 · hard

  • A.相同位数可取更大范围
  • B.纯二进制却更节省空间← 正确答案
  • C.BCD 码可直接相加运算
  • D.二进制可作十进制显示

答案:B。4 位纯二进制可表示 0 到 15,而 BCD 只表示 0 到 9,所以纯二进制更省空间。BCD 码加法需要加 6 修正,不能直接相加;二进制数也不方便直接作十进制显示。

Q8. 下列哪些属于格雷码的典型工程应用?

多选题 · mid

  • A.旋转编码器← 正确答案
  • B.电梯楼层显示← 正确答案
  • C.FIFO 读指针← 正确答案
  • D.浮点数运算

答案:ABC。旋转编码器、电梯楼层显示和异步 FIFO 指针都利用“相邻码只变一位”来避免多位同时变化带来的误读。浮点数运算有自己的 IEEE 754 标准,与格雷码无关。

Q9. 关于奇偶校验码,下列说法正确的是?

多选题 · hard

  • A.能检测单比特翻转错误← 正确答案
  • B.能检测偶数个比特翻转
  • C.不能指出出错的具体位置← 正确答案
  • D.能纠正一个比特的错误

答案:AC。奇偶校验只统计 1 的个数奇偶性,因此只能检测奇数位翻转(如单比特错)。偶数位翻转后奇偶性不变会漏检;校验结果只有 0/1 一个值,无法定位位置,更不能纠错。

Q10. 在异步 FIFO 设计中,读写指针用格雷码表示的主要原因是?

多选题 · extreme

  • A.降低多位同步亚稳态风险← 正确答案
  • B.比二进制指针占用更少位
  • C.相邻指针只差一位更安全← 正确答案
  • D.可以直接比较读数的大小

答案:AC。异步 FIFO 的指针要跨时钟域传输。二进制指针跳变时多位同时翻转,采样瞬间可能读到中间乱码;格雷码每次只变一位,即使采样在翻转瞬间,也只会差一位而不会跳到错误位置。格雷码不省位数,也不能直接比大小。