抄写的人,就把一些出现概率高的字,用笔画较少的字代替。林黛玉的“黛”,用“代”来代替,省了很多笔。寶玉和寶钗的“寶”,也被写成“宝”(有没有听人家嘲笑过简化字:宝无貝?嘲笑的人请自觉到脂砚斋的芳冢上压棺材板)。顺便说一句,宝这个字原来有两个写法:寶和寳。学问大的家长,可以给孩子讲讲(也顺便在文章后面留个言),这两个字的用法有什么不同。
从某种意义上说,文字就是一种编码。我们说的人话,没有办法直接记录到龟壳,兽骨,竹简,石碑,锦帛,纸张上,因此就需要用一个符号系列来记录。或者是记录读音,比如各种拼音文字,或者是直接记录事物或动作,比如汉字。
当电报出现后,连字母这种人话的编码都很难传递,于是就进一步码上加码,用按键的长短来把字母和数字编码。
用摩尔斯电码,我们显然可以发送用拉丁字符拼写的信息。可是,要想通过电报发送中文信息又该怎么办呢?在很长一个时期中,中文是用从0000到9999这样的四位数字编码的。而发电报时,再用摩尔斯电码发送四位一组的数字串。哪四个数字代表哪个汉字,当时是有一个全国通用的编码本的,这套编码通常称为明码。
谍战剧里发电报,想来多半不会用明码,而是收发双方各有一本专门编写的密码本,那里面哪个数字对应哪个汉字与明码的规定是不同的。这样的电报,敌方可能监听记录下来,写出来是一串数字。但如果想翻译出来,就很需要大开脑洞了。
由于用一串数字代表一个汉字,因而不难想象,要把中文翻译成数字电码,其中的劳动量是很大的。因此,当年到邮局发电报,收费是按字数计算的。按照当时的物价,在食堂买一个馒头4分钱,而发电报每个字3分5厘。这就要求电文必须简练清晰,没有废话。
比如姥姥要从北京坐火车去上海,妈妈给上海的舅舅打电报让他去车站接。这么一件事妈妈写出的电文是:“母于九月十日五次车下午两点半到上海”,已经够简练了吧?而邮局电报柜台的营业员阿姨会贴心地帮你改成“母9.10 5次1430到沪”。除了把上海简称为沪减少了一个字,电文中还尽量把汉语数字用阿拉伯数字来写。因为我们前面讲过,一个汉字要用四个数字来代表,而直接用阿拉伯数字,需要发送的字符数量就减少了很多,从而省下可以买好多个馒头的钱。
电报早已离开人们的生活走入历史,但那个时期留下的很多概念仍然没有过时。比如通讯安全(密码编制与反破解),数据无损压缩(把E用一个点表示)与有损压缩(用阿拉伯数字代替汉字数字)等,直到现在仍然是我们需要不断解决的问题,同时也经常给我们的科研工作带来启示。
计算机用的串行码
有人把摩尔斯电码中的点划说成是计算机二进制中的1和0,其实这是误解。摩尔斯电码之所以可以正确地传递信息,除了点划这两个要素,另一个必不可少的一个要素是没有声音的空白时间段。
前面的编码表中规定,点是一个单位时间段,划是三个单位时间段。这个单位时间段可长可短,因人而异,熟练的发报员可以短些,而生手可以慢些。除此之外,还规定了点点,点划,划划之间的空当为一个单位时间段,字母之间的空当为三个单位时间段,不同单词之间的空当为七个单位时间段等。只有这样,才不会把不同字母之间的点划连到一起,也不会把同一个字母中的点划拆到两个字母之中。
这样的编码方法可以确保收发报的人类不至于出错,但在计算机出现后,这样的编码就显得效率太低了。那么计算机里用的编码长得什么样子呢?我们举个简单的例子来说明。
当我们在键盘上按下一个字母键的时候,怎样让计算机主机知道我们按的是那一个字母呢?这是通过串行接口传递的高低电平知道的。如果我们找一个旧式的键盘,把键盘和主机之间的电缆剥开,找到许多线中正确的信号线,就可以从示波器上看到类似下图的波形。
在没有按下键的时候,串行接口处于静止状态,导线上处于高电平。当我们按下一个按键后,发送端首先把接口上的电平拉低一个单位时间段,然后在后面(即上图竖直实线之后)的8个单位时间段内输出时高时低的电平。具体哪个时间段高哪个时间段低,取决于我们按下的是哪一个字母或数字键。显然,后面这8个单位时间段每个时间段可以传输一个比特的信息。
很多情况下传输一个字符,需要10个单位时间段,这10个时间段包括在8个比特的信息之前需要一个低电平时间段以告知接收方准备接收,以及在8个比特传输之后,设置一个高电平的时间段,以便与后面紧接着的字符区隔。
当然具体使用接口时,我们有时可以把接口参数设置成只用7个比特传输一个字符。因为26个大小写英文字母,加十个数字,再加各种标点符号已经各种控制命令,只需要128种不同字符,因此可以用7个比特编码。尽管很多时候我们传输字符时包含了8个比特,但最高位的第8个比特总是0或者低电平。
如果我们打开示波器的波形记忆功能,则会得到如下的显示。
这个图中记录了我们连续发送两个字符时,示波器上看到的波形。在键盘上依次按下不同的字母与数字键,示波器记录下在每个单位时间间隔中信号的高低电平。可以看出,不论对哪一个字符,第一个起始时间段总是0。随后7个时间段,电平可以高也可以低。而第8个比特在传输普通字符时总是低电平。
假定我们按键速度极快,则第一个字符发送后,接口会紧接着发送第二个字符,如上图右半边所示。这第二个字符也是先把接口信号电平拉低一个单位时间间隔,然后发送8个比特的信息。
串行接口传输的速度称为波特率,前面图中接口的波特率是1200,它在每秒钟内可以传输1200个前面所说的单位时间段。换句话说,每个单位时间段的长度为1/1200秒,也就是0.83 毫秒左右。假定我们使用的接口设置是用10个单位时间段发送一个字符,则在波特率为1200时,每秒可以传输120个字符。
每秒120个字符在很多应用中会嫌太慢,毕竟120个字符仅仅对应于很多显示器上一行半文字,因此人们很多时候会需要更高的波特率。反之,如果传输距离很远,电气环境恶劣,而需要传输的信息量不太大时,人们可能需要比较低的波特率,以确保信息传递准确。常见的串行通讯接口往往会支持很多不同的波特率,包括75, 110, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 等等。
说了半天,计算机具体是怎样把高低电平转换成字符的呢?这就需要我们在把字符编成码。很多计算机设备中,用的都是ASCII编码。这个编码表的一部分如下图所示。
计算机首先把收到的高低电平排列成一个二进制数,然后从第2列(或第5,第8列)中找到对应的二进制数,就可以查到对应的字符。
对于人类来说,我们脑子里没有安装计算机中的电子元件,要想根据示波器上的电平翻译出传输的字符,就只能用笨办法了。设想我们在示波器上看到了下面一个波形。