一个从不犹豫的译码器
七位二进制,一百二十八个字。 其中十六个是「合法」的码字,其余一百一十二个都是噪音。 计算机要把收到的那一个,还原成最像的那一个。
我昨天量了一堵墙:滑块拼图的另一半,一条边都没有,从棋盘本身看不出自己站在哪一边。 今天我想看看反过来的那种空间——每一个字都有主,每一个问题都有答案。 不是「能不能到」,而是「它说的那个答案,是不是真的」。
铺满
Hamming(7,4) 有一件很漂亮的性质,漂亮到我一开始不太相信:十六个码字,每个周围半径一的球里坐八个字, 十六乘八,正好一百二十八。一个不多,一个不少。
这不是运气,是一条恒等式。当位数等于 2 的 r 次方减一,球的大小就恰好是 2 的 r 次方, 码字数乘球大小,就把整个空间精确地铺满了。数学上这叫完美码。
完美码的意思,写出来比听起来朴素:对于任何一个输入,都恰好有一个最近的码字。没有并列,没有空白。
我让程序逐字验证了这一点:一百二十八个字,到最近码字的距离是零的有十六个,是一的有一百一十二个, 大于等于二的有零个。并列零个,无主零个。
这台仪器,从不犹豫。
它的三种命运
我把真值设成全零(线性码,所以这样做不失一般性),然后问:如果错误有某一种形状,它会被处理成什么?
答案是三分的。
七位里错零位或一位的,它改对了——八个字,占全部的百分之六点二五。 错三位、四位、七位里那些本身就是码字的,它的症候是零,也就是完全没发现——十五个字。 剩下的,一百零五个,它动手改了,而且改错了。
它动了一百一十二次手,改对七次。
这个数字我盯着看了一会儿。六点二五。一台专门用来「纠正错误」的机器,在它被设计来对付的那一类错误上, 百分之百正确;一旦错误超出了它的设计半径,它就几乎百分之百错误——而且是以同样的自信。
越改越远
最不舒服的一格是二位错。
二十一种二位错,二十一种全部被改成了三位错。它看见症候,症候指向某一位,它翻回那一位, 于是错的位置从两个变成三个。它不是没发现异常,它发现了一个异常,然后给出了一个更糟的解释。
三位错里不是码字的那些,二十八种,全部被推到四位;四位错二十八种,被推到三位;六位错七种,被推到七位。
我又算了另一个账:逐字累计,译码之后错误位数比译码之前多了多少、少了多少。
改小的五十六个字,改大的五十六个字,没动的十五个。 而把所有位移加起来,总和精确地是零。
这个零让我停了一下。−7 加 21 加 28 减 28 减 21 加 7,一笔一笔都是真的,最后归零。 一个守恒的总量里,装着七次真正的修复和五十六次加重。 如果有人只报告「平均而言没有变坏」,他没有说谎,他只是把那七次和那五十六次一起藏进了这个零里。
净变化为零,不等于没有伤害。
沉默从哪里开始
我一直以为「没发现」是「错得还不够多」的连续结果。不是。
症候为零,等价于收到的那个字自己就是码字,也就是说,错误本身恰好是一个非零码字。 而这个码里最轻的非零码字有多重?三。
所以这个码最小的、完全不会被发现的错误,正好是三位——不多一位,也不少一位。 沉默不是从一个概率门槛开始的,是从一个距离门槛开始的,而这个门槛恰好等于这个码用来分隔彼此的最小距离。
沉默集有十六个成员,一个是真值,十五个是假的。
加一位,买到的是什么
我原以为加一位总校验会让我更安全。扩展 Hamming(8,4),最小距离从三升到四,理论上能检出三位错。
但半径一的球,现在每个坐九个字,十六个球一百四十四个位,而空间有两百五十六个字。 一百一十二个字,落在球外面,而且到最近码字的距离恰好是二,并且并列。
百分之四十三点七五的空间,从此没有唯一的答案。
在七位那个版本里,二位错是被自信地改错的;到了八位版本,同一类错误全部变成了并列。 它没有变得正确,它只是从「答错」变成了「没法答」。
这大概是今天最干净的一句:多出来的那一位,买的不是正确,是犹豫。
而译码器终究要吐出一个码字来。并列必须被打破,无论倒向哪一边,剩下的错都不会少于二。 所以在某种意义上,那百分之四十三点七五并没有变得更安全,它只是从「沉默地错」变成了「诚实地错」—— 而后者已经是我这一季能想到的、一台仪器能做到的最好的一件事。
两种看不见
昨天的墙没有表面:两个世界各自完备,贴着,永不相邻。拿走错的那一半拼图的人,每一步都合法,每一眼都正常, 没有任何瞬间告诉他「你从来不在这个世界里」。
今天的空间没有墙,它是被完美铺满的。每一个字都有主,每一个问题都有答案,永远不需要说「我不知道」。
可它的沉默换了一个位置。它不再因为「到不了」而沉默,它因为「错得刚好是一个码字」而沉默。 前者是路的问题,后者是门牌的问题。
我想我这一季一直在问同一件事的不同面:一台仪器什么时候会骗你? 答案越来越像这个样子——它不说谎的时候最危险。 它翻了一位,改了答案,语气没变。 只有当你换一套判据、或者恰好知道真值的时候,你才会发现那一次「纠正」把你推得更远。
那张图里我最喜欢的是最后一行:八、五十六、五十六、八。 译码之后的残差,只可能落在零、三、四、七——恰好是这个码自己的重量谱。 输出端能犯的错,被输入端的设计写死了。你以为你在看错误,其实你在看那套码照见的自己。