要理解汉字是如何被计算机处理的,首先就要理解编码原理。 其实不光汉字;实质上,计算机内部的一切符号都要借助编码来输入输出。 千字文 比如,我们可以用这篇千字文作为编码依据,写出数字1,就对应于天;写出数字2,就对应于地……那么,我们就可以用最多四位数字把所有这些字表示出来。 然后,如果咱组织个天地会的话,就可以用数字1 2作为接头暗号;或者,更中二一点——左手一个指头指天,右手两个指头指地…… 更精细点的话,我们可以把每个手指的伸曲作为不同的编码;那么两只手10根手指就能编码1024个不同文字——左手伸一下拇指,收回;然后再伸一下食指…… 接头人一看:哎呀同志!可算找到组织了! 咳咳。不开玩笑了。 总之,我们看到了,文字是可以用其它方式“曲折隐晦”的表达的。 既然手指的伸曲可以作为一个不同的状态、使得我们一双手伸20次就能吟咏完这首诗: 白日依山尽,黄河入海流。欲穷千里目,更上一层楼。 那么,用10根电线的不同通电状态组合,是不是也能编码这篇千字文? 没错。这就是数字电路原理。 我们把电线有电叫做状态1,电线没电叫做状态0;于是,00000 00001就是一个状态,而00000 00010是另一个状态——规定每个位的电信号权值为2^n,其中n是第n条电线,从0开始编码:这就是二进制数字。 二进制拿来记录处理电路状态实在太方便了;因此,计算机里面习惯用二进制描述电路状态。比如,寄存器当前值是00000 11000、地址线收到一个信号00100 11011,等等。 请记住,这并不是说电路里神奇的出现了0和1,而是我们把电路断开(无电)叫0、电路闭合(有电)叫1,从而可以用0/1组成的数字串简洁的把“一把导线里面每根线的电压状态”表示出来。 如果不明白的话,请反复诵读这句话:00100 11011 应该读作 断断通断断 通通断通通。 二进制用起来还是不够方便。 事实上,按照每位的权值是2^N的规则(和十进制计数法每位权值是10^N一模一样),我们可以很容易的把它转换为十进制表示——注意只是表示。 比如,电路状态 断断通断断 通通断通通,对应的二进制表示为00100 11011,十进制表示为155,十六进制表示为98——表示成十进制、十六进制短了很多,方便记忆了;但却不再能直观的看出电路的通断状态:必须转换回2进制,才知道这个状态是 断断通断断 通通断通通。 总之,这个状态是电路上实实在在的物理状态,拿万用表可以测出来。我们把这个东西叫做机内码。 所谓编码,就是把千字文、阿拉伯数字以及康熙大字典中的每一个字对应到机内码的过程。 比如,空格" "对应于十进制的32、十六进制的20以及二进制的00100000;阿拉伯数字"1"则对应于十进制的49、十六进制的31以及二进制的00110001……以此类推。 可以看出,这个编码可以是一个极其随意的过程。 比如,我很随意的用千字文编码;但发明计算机的美国佬却用ASCII码先编码了英文字母、阿拉伯数字以及!@$#^%之类符号 ;其它各国在引进计算机时,也会自说自话的搞出自己的编码方案、从而把本国语言文字输入计算机…… 比如,我国就有GB2132、GBK、GB18030等汉字编码;但台湾、日本、韩国以及东南亚国家也用汉字,他们也搞了个另外的好多套编码…… 那么,这一大堆编码方案,谁说了算? 不然的话,按你的编码,99 67 54是520,结果到法国佬那里成了250……你们还不要打起来啊? 所以,现在搞了一个全球统一的Unicode码,一网打尽全球所有语言。 编码完成之后,汉字就可以和罗马字母、法文字母、德文字母、俄文字母、英文字母一样,以电信号有无/磁化方向/光盘上的凹坑等等不同状态存储起来了。 其中,在光盘上时,它是一串凹坑的组合;在硬盘上,它是一组磁畴的磁化方向;在内存条里,它是场效应管的充电状态;在并行总线上,它是一把金属导线的电压高低组合;在串行通讯线缆上,它是高高低低的一组方波…… 所有这些状态,都可以用二进制表示;所有这些二进制,都可以转换成更方便阅读和记忆的十进制/十六进制数字——但想要直观的理解电路状态,都必须还原到二进制。 我们知道,键盘上面只有26个英文字母以及十个数字和!@#$% 等特殊符号,以及tab、shift、enter等控制键(但也可以用来输入)…… 你看,没有汉字啊?这怎么办? 事实上,键盘输入,归根结底也只是电信号而已。 既然我们已经用abcd、1234等等编码了这些电信号;那么,把这些电信号翻译回12345、然后直接用12345这些按键上的字符、拼凑出每个汉字的Unicode码——这,不就解决了输入问题吗? 嗯。别急,别急。我知道你记不住。没人能记住超过六万个汉字的Unicode编码。 这个办法的确行不通;但这个思路是成立的,对吧? 既然思路成立,那么不要急,一步一步来。先找出问题,再一步步解决它。 现在的问题在于,用这种方法敲汉字,我们第一记不住编码表,第二只能利用数字小键盘,输入效率太低。 怎么办呢? 没错。拼音。我们把二十六个英文字母当拼音,把每个汉字的读音敲进去,不就好了? 没那么简单。普通话一共才几百个音,汉字六万多……同音字实在太多了。这怎么输入? 没错。笔画输入。汉字归根结底有五种基本笔画,横竖撇捺折对应12345,妥了——比如王字怎么写?横横竖横,1121,哈哈搞定。 仍然不行。遇到工字和土字,你怎么办? 所以现在的问题是重码,对吧? 好办。把重码字列出来,给用户选择。这下妥了吧? 没错。解决了。 甚至于,拼音输入也能这样解决。 不仅如此,既然普通话只有几百个音,那没必要敲全eng、ang吧? 给eng/ang也来个编码,敲两下,一个音就进去了——哈哈,双拼! 但这样仍然不好用。每敲一个字都要在候选字里面找半天,这实在太慢了。 还得继续优化。 现在有两个思路。 一是王永民先生搞的五笔输入法,思路是从编码汉字的偏旁部首入手设计一套字根表,一方面减少了每次输入的击键次数,另一方面减少乃至杜绝了重码。以至于五笔高手可以轻易做到每分钟输入超过200个汉字。 但五笔输入法需要专门的训练。背字根表,反复练习直到形成肌肉记忆…… 因此,另一条思路获得了更多支持,以致于现在只有专业录入人员才会学习五笔。 这个思路就是:继续使用拼音输入法;但尽量让用户一次输入一个词、一句话;那么借助软件强大的分析能力,就可以“猜”出他最可能想说什么。 打个比方的话,你说“lin”,没人知道是哪个字;但你说“树林”“林黛玉”“临安”“临颍”“淋雨”,这个字就唯一确定了。 当然,单字仍然无法确定;有些词也有同音。但无论如何,这个策略使得重码少了很多。尤其借助概率论的马尔科夫链理论,整句输入可以得到极高的准确率,几乎不用选字,从而使得熟练的拼音使用者也能一分钟输入一百字以上。 总之,汉字的输入是一个编码的嵌套过程:先是击键产生一个键盘码,键盘码被键盘内置的CPU转换成对应的ASCII机内码(并行线路是通断错落的一组电平,串行线路是一组方波);然后这些ASCII码的组合(比如ABCD)又被转换到汉字机内码(Unicode或者GB2312/GBK/GB18030)——最终,这些机内码被保存到磁盘/光碟等存储介质,汉字从输入到储存这一条龙过程就算走完了。 注意这里面反复进行了多次编码和解码;但编码/解码过程各自独立,互不影响。 比如,你可以用拼音或者五笔编码汉字、然后以这个编码输入;然后输入法解码你敲入的键盘字符序列,再自动帮你编码到Unicode或者GB系列。 从哪个途径转换我们不需要关心。只要最终得到的Unicode正确。 编码和存储搞定了,怎么输出呢? 比如,见了12354这串数字,你怎么知道它应该是哪个汉字?这个汉字该怎么写? 在回答这个问题前,我们应该先想一想:屏幕上是如何显示汉字的? 我们知道,屏幕是由一个个像素构成的。正如我对着自己显示器拍的这张照片,像素的不同取值就构成了汉字的笔画,最终组成我们见到的汉字。 那么,像素的黑白,岂不是也可以用0和1编码吗? 没错,这就是点阵字体: 正字的Unicode编码是十六进制的6B63,而6B63这个机内码关联到一副bitmap(位图),这张位图也可以用二进制编码,就是上图右侧那那一堆数字——按顺序存下来,就是正字的16位点阵。 类似的,还可以搞32位或更大的点阵,从而把字体显示的更精确一些。 总之,六万多汉字就对应着6万张不同的点阵图片。 我们知道,汉字有不同的字体。比如楷书、隶书、宋体、仿宋,等等。这些就对应着不同的小图片。 因此,每个不同字体又对应着不同的六万张小图片,你装了100种字体,电脑里就有了六百万张不同的图片。 将来,当需要显示汉字时,从Unicode找到对应的图片(也就是那一堆二进制串),再按照指示给显示器不同的像素通电/断电,于是显示器上就黑白分明的显示了不同汉字。 当然,显示器的显示原理也各不相同。比如,CRT是电子束轰击荧光粉,没有电子轰击的地方就不发光;而LCD呢,哪里通电“搅乱”的液晶,哪里就混浊不透光;LED,哪个发光管通电哪个发光…… 因此,具体显示时,显示器也还需要“翻译”一下。比如CRT遇到0就改变电子枪栅极电压,不让电子飞出去;而LCD遇到0就切断对应像素的电压输出,让液晶恢复透明…… 不仅如此。 不同显示屏尺寸不同、每英寸像素数也大相径庭。32点阵的汉字,在某些屏幕上占地太大,一屏显示不了几个;但在视网膜屏上又显得太小,拿放大镜才看得见…… 怎么办呢? 的确可以通过插值的方式缩放;但这样效果并不好(插值是一种通过算法自动添加像素的方式,比如正字放大一倍显示时,就要把横从一排像素改成两排;但如果缩放不是整数倍、或者笔画弯折处就很难确定该不该插入像素)。 另一种方式是,不记录像素,记录“写字过程”。比如线条从哪里起始、在哪里转折、到哪里结束,以及哪里下笔重、哪里下笔轻,等等。 这就是所谓的“矢量字体”,它记录的是笔画线条以及转折、粗细等信息,因此可以非常方便的缩放。 不仅如此。你可能注意到,我拍摄的实际屏幕照片里,“评论”二字笔画边缘颜色有些发暗。 这是clear type处理后的结果。经过这个处理后,字体看起来笔画更光滑、更锐利、更美观。 换句话说,字符输出并不像想象那么简单。它可能需要矢量图缩放、点阵图转换、cleartype/truetype之类技术处理点阵图(注意这里是彩色点阵,这种点阵里,每个像素又分为红绿蓝三个分量,每个分量又有256级亮度),然后才能照图施工、把文字输出到屏幕上。 这就是汉字输入输出的全过程。 |
|