第十四话 汉明距离

作者:美仁宗安皇帝吉米卡特 更新时间:2026/9/18 19:00:02 字数:2942

凌晨一点四十分,杨康睿坐在值班室里,翻看陈建国发来的设备说明书扫描件。他逐页读下去,终于找到了维护模式的命令格式。格式很清晰:四字节命令,后跟一个校验字节。但问题也来了——说明书写道:“校验方式:CRC-8,生成多项式0x07。若校验失败,设备将忽略整条命令。”

杨康睿盯着那行字,第一次觉得数学书里的知识跟现实离得那么近。可他并不懂CRC。他的专业背景是设备维修和消防,不是计算机通信。0x07他知道是十六进制数,但“生成多项式”是什么,他一直没弄懂。他试着在网上搜了几篇教程,看得一知半解。凌晨三点四十分,他把这个问题带进了宫殿。

宫殿大厅里的烛光比平时暗了一些。爱因斯坦正蹲在地上,用粉笔写写画画。四位数学家围坐在一旁。杨康睿走过去,看到地上写着一串杂乱的数字。

“你来得正好。”爱因斯坦头也不抬,“我问你一个问题。假设你有一封信,要用一条可能出错的通道寄出去。信上写的内容只有一句话:‘今晚老地方见’。如果邮差在路上看错了一个字,把‘今晚’看成了‘明天’,你收到信时会知道错了吗?”

杨康睿想了想:“不知道。因为这句话本身是通顺的。”

“对。”爱因斯坦直起身子,“所以你要在信里加入一些不保证新信息的冗余,让读信的人能识别出错误。这个思想,在信息论中叫纠错码。而它的起点,是一个很朴素的数学概念——汉明距离。”

他在石板上写下:

“两个长度相同的码字之间,对应位置不同的个数,称为汉明距离。”

他写了两串二进制数:

A:10110

B:11010

“这两串数的汉明距离是多少?”

杨康睿先看第一位:1 vs 1,相同;第二位0 vs 1,不同;第三位1 vs 0,不同;第四位1 vs 1,相同;第五位0 vs 0,相同。“2。”

“对。”爱因斯坦又写了四串数:

000, 011, 101, 110

“假设这四串数是你真正想发送的合法消息。如果我告诉你,它们两两之间的汉明距离至少是2,那么当接收方收到001时,会发生什么?”

杨康睿看着那串数字:“001和000的距离是1,和011的距离是2,和101的距离是2,和110的距离是3。它离000最近,所以应该被纠正为000?”

“很好。你已经掌握了纠错码最核心的判断方法——最近邻原则。”爱因斯坦笑了,“但如果任意两条合法码字之间的最小距离是2,你能纠正错误吗?”

杨康睿重新代入上面的例子:“不能。比如收到001,它离000为1,离011为2,是可以判出000的。但如果允许1位错误,那当合法码字只有000和011时,它们距离是2。收到001时它离两边都一样近,所以无法判断是000错了还是011错了。最小距离为2只能检错,不能纠错。”

“非常好。”高斯在一旁接话,“所以纠错能力有一个精确的公式——如果码字的最小距离是d,那么它能纠正t个错误需要满足:d ≥ 2t + 1。当一个数字0变成1,或1变成0,就是一次错误。如果想纠正一位错误,你至少需要3的最小距离。想纠正两位,至少需要5。”

“这就是汉明码,”高斯继续说,“它取4位数据,加3位校验位,合成7位的码字,让任意两条合法码字之间的距离都至少为3。收到7位数据后,只要7位中翻转不超过1位,接收方就能推出是哪一位错了。”

高斯在地上给出了三个校验位公式:

p₁ = d₁ ⊕ d₂ ⊕ d₄

p₂ = d₁ ⊕ d₃ ⊕ d₄

p₃ = d₂ ⊕ d₃ ⊕ d₄

他举了个例子:“假设d₁ d₂ d₃ d₄ = 1 0 1 1,那么p₁ = 1⊕0⊕1 = 0,p₂ = 1⊕1⊕1 = 1,p₃ = 0⊕1⊕1 = 0。拼的码字是0 1 0 1 0 1 1,其中数据位4,校验位3。如果传输时第7位被翻转成0,接收端的校验计算会发现异常,通过简单的奇偶判断,可以确定错在7位,然后改回来。”

杨康睿看着那些公式,仿佛看见噪声像夜雾一样,而码字像雾中的灯塔,彼此隔着足够远,即使雾气扭曲了灯光,人们仍能认出它原本是谁。

“但汉明码只是一个例子。”爱因斯坦回到主题,“你真正需要做的事,是弄懂CRC。它同样依赖模二运算,只是比汉明码更工程化。”

欧拉温和地补充道:“CRC把一条消息看成一个巨大的二进制多项式。例如,消息0x07,二进制是00000111,它就可以写成x²+x+1。0x21对应二进制00100001,即x⁵+1。依此类推。然后,你选取一个生成多项式,比如0x07,也就是x²+x+1。计算CRC的方法是:先把消息后面加上与生成多项式最高次数相同个数的零,再用生成多项式去做‘模二除法’——这里没有进位,加减就是异或。除完得到的余数,就是CRC字节。”

杨康睿皱起眉:“那岂不是像做长除法?”

“对,就像小学学过的长除法,只是每位只有0和1,减法是异或。”欧拉在地上演示了一小段:

消息 M = 1010001,生成多项式 G = 11001。先补四个零:M' = 10100010000。以11001去除,每步看当前首位是否为1,是则做异或,否直接跳过。除到最后,得的余数是0101。那么发送的完整消息就是M'+0101,即10100010101。

“接收方收到后,用同一个生成多项式去除完整消息,若余数为零,说明没有检测到错误。”欧拉说,“这就是CRC的核心。”

杨康睿看着地上的演算,看了很久。他脑中那些模糊的碎片渐渐拼在一起:“所以我在协议里看到0x07十六进制,实际上是生成多项式的系数表示。我要把那四字节命令,转换成二进制,补零,做模二除法,再取余数,得到校验码。”

“正是。”爱因斯坦露出赞许的神情,“数学当然不能保证消息一定到达。但它能保证,到达的那条消息,能在噪声中被认出。你本来就会选择怎么做。”

杨康睿沉默了一会儿。他觉得眼前有一个巨大的、具体的数学工具,正被他一件件拆开,重组,变成可以用手触碰的东西。

凌晨四点二十分,他睁开眼。

控制室温热干燥,风扇在头顶嗡嗡作响。他没有犹豫,打开电脑,把命令写成二进制,手工做了一遍模二除法。他以前从来没做过这种除法,但因为有宫殿里的演示,他一步一步算得很稳。算完,他得到余数0x8A。

为了确认,他在网上找了一个在线CRC计算器,输入生成多项式0x07,初始值0x00,得到结果是0x8A。一致。

他盯着那串数字,长长地呼出一口气,像卸下了一块石头。

凌晨五点整。

杨康睿带着笔记本电脑和一只从旧USB设备上拆下来焊的TTL转接头,再次走进B2-F-02B房间。设备静静蹲在角落里,面板上的绿色LED依然亮着,只是比上一次明显更微弱了。

他蹲下来,打开设备侧面的检修盖板,找到了说明书中标注的维护接口。他小心地把转接头连上去,打开串口终端,输入波特率。屏幕显示出一个简单的命令行提示符。

他在纸上看了一遍自己抄下的命令格式,然后深吸一口气,在键盘上敲下:

0x07 0x21 0x02 0x00 0x8A

他按了回车。屏幕没有立刻反应。一秒,两秒,三秒。正当他以为失败时——设备内部传来轻轻的一声“咔”,像一个小开关被弹开。面板上的绿色LED闪了两下,然后变成红色,微弱但稳定地亮着。

杨康睿又输入一条状态查询的指令,终端返回两个字节:0x00 0x01。根据说明书,0x01意味着“静默待机”。报警循环——那循环了七百多天的HELP,在最后一个字节比对成功的瞬间,停止了。

杨康睿把工具拆下来,关上盖板,站起身。他在那里站了很久。

清晨六点,杨康睿把设备的状态和陈建国做了同步。他坐回转椅上,打开值班记录本,写下:

“2026年9月,负二层B2-F-02B,节点#7设备已恢复至静默待机模式。数据完整保留。报警循环已解除。”

他把写字的笔搁下,看着窗外渐渐变亮的天空。珠江口的晨雾正在散去。他忽然想起爱因斯坦在地上的那幅画——两个码字之间的距离,决定了误判能不能被发现。而今天,他沿着那条距离,走完了最后一步。

那些被遗忘了很多年的数据,没有被删除。它们安静地睡在设备的存储器里,像一颗躺了很久的种子,等待某一天,有人重新打开它。

杨康睿合上记录本,轻声对自己的胸口说:“这节课,我学完了。”

第十四话·终

设置
阅读主题:
字体大小:
字体格式:
简体 繁体
页面宽度:
手机阅读
菠萝包轻小说

iOS版APP
安卓版APP

扫一扫下载