郭连骐
(哈尔滨工程大学 信息与通信工程学院,黑龙江 哈尔滨 150001)
几千年来,人类记录历史、传递信息的主要工具是文字。计算机中、数字通信中的文字需要编码——文字信息交换码。文字编码效率越高,生成的文字文件就越短,存储时更省空间,传输时更省时间,经济效益也就越高。所以,人们研究文字编码追求的最主要的目标是提高编码效率。目前,世界上广泛使用的文字编码是ANSI 码和Unicode 码。美国人发明了数字电子计算机,不但要用于科学计算,还要用于文字信息处理。他们的母语是英语,就为英文字母(基本拉丁字母)及符号(包括阿拉伯数字、标点符号等)设计了一套信息交换码作为美国的国家标准,American National Standards Institute,简称ANSI 码。这些字符又称为ASCII 字符(American Standard Code for Information Interchange )。
英文字母及符号占用1 个字节的前半段(0 至127)编码,每个字符的码长是1 个字节。
其他国家制定本国的文字编码标准时也都与ANSI 码兼容,即保留英文字符原有编码数值不变。俄文、希腊文等字符较少的拼音文字,使用字节的后半段(128 至255)编码,字符码长也是1 个字节。中国汉字、日文等字符数量较多的文字需要2 个(或更多)字节编码,其第一个字节也只能使用字节后半段(128 至255)编码。如此生成的多国文字编码标准组成了庞大的ANSI 码体系,我国的文字编码国家标准GB18030—2000[1]就属于此体系。本文中“ANSI 码”一般泛指ANSI 码体系。
由于俄文、希腊文、汉文、日文等许多种文字都使用相同的空间(首字节的后半段)编码,所以这些文字编码标准是不可以同时使用的,即这些文字编码是不独立的。这是ANSI 码体系与生俱来的缺陷,给用户带来不便。
为了多种文字编码可以同时使用,国际标准化组织推出了国际标准——“通用多八位编码字符集”(Universal Multiple-Octet Coded Character Set),简称Unicode 码。
该码中各种文字都有各自的编码空间,所以它们都是独立的。国际上使用比较多的文字,如英文、俄文、汉文(比较常用的汉字)、韩文、日文等的编码在“基本平面”内,每个字符的码长都是2 个字节(区号、位号)。使用频度很低的文字(包括中国数万极少使用的汉字)码长是4 个字节(组号、面号、区号、位号)。
英文、俄文、希腊文等许多拼音文字在ANSI码体系中,字符码长是1 个字节,它们在Unicode码“基本平面”中字符码长是2 个字节,编码效率降低了一半,编码效率低是Unicode 码的最大缺点。
世界上大多数人使用拼音文字,由于Unicode码编码效率太低,他们无奈就只得使用ANSI 码体系。在以字节为编码单位不变的情况下,这种局面无法改变。
一个文字编码的平台中,各种文字的编码应该是独立的,各种文字的地位应该是平等的。
ANSI 码体系虽然包括了许多国家的文字编码标准,但是它不能称为文字编码的平台,因为不仅各种文字编码不独立,而且其他文字与英文的地位也不平等。
Unicode 码虽然效率很低,但它是目前唯一可使用的文字编码平台。
一种比较理想的文字编码平台,不仅各种字符都有独立的编码,而且它们要有比Unicode 码、ANSI 码体系更高的编码效率。
郭码是一个从核算单位开始、完全原始创新的文字编码平台,由7 种编码方法组合而成。各种文字在郭码中都有独立编码,并且编码效率都比ANSI 码提高了约30%,比Unicode 码提高得就更多。
世界上有上百种文字,各种文字所包含的字符数量相差悬殊。例如,英文有大小写字母52 个,中国汉字有约10 万个,是英文字母数量的1000多倍。
ANSI 码和Unicode 码以字节(二进制的8 位,容量为256)为单位对各种文字编码,1 个字节容量不够就使用2 个字节,再不够就使用4 个字节。运用这个单一方法,对上百种、包含字符数量相差上千倍的文字编码,编码效率不佳也就在所难免。
郭码设计了新的核算单位——“组元”和“半组元”,“组元”是二进制的12 位,容量为4096,是字节容量的16 倍,可以表示的数字是0 至4095;“半组元”是二进制的6 位,容量为64,可以表示的数字是0 至63。
Unicode 码的编码空间由4 个字节构成,依顺序分别为组号、面号、区号、位号。2 字节的容量是65536,3 字节的容量是16777216(1600 多万),4 字节的容量是近43 亿。Unicode 码的组号只使用了0至127,故它的总容量是2147483648(21亿多)[2]。
2 个组元的容量是16777216(4096×4096),与3个字节的容量相同,故2 个组元就足以为全世界的文字编码。
本文中所称“全世界的文字”的意思是,中国汉字以外的文字基本上是以“GB13000.1—93 ISO/IEC 10646.1—1993”[2]为参照物,中国汉字按10万个考虑。
汉字有真、草、隶、篆等多种写法,书法作品中有“百寿图”,有书法家声称:“寿字有5000种写法”,书法艺术创新是没有止境的。对于书法艺术中的文字郭码都不予考虑,郭码只专注于人们日常交流信息使用的文字。
郭码包括多种编码方法,其中最基础的编码方法是“基本方式”编码,它是2 组元的区位码,第1 个组元是区号,第2 个组元是位号。
ANSI 码和Unicode 码形成的文字文件中以字节为单位,流淌的是“字节流”。郭码形成的文字文件中以组元为单位,流淌的是“组元流”。
Unicode 5.0.0 版数据显示,它已经给近10 万个字符编码,其中有6 万多是中国汉字。考虑到还有3 万多中国汉字没有编码,以及数千个藏文“垂直预组件”没有编码,郭码准备为约14 万个字符编码。
一个组元可以表示的数字是0 至4095,郭码对组元值范围做出设定:
“0”暂时不用。区号递减排序,为4095 至4051,45 个区。位号递增排序,为1 至4000,4000 个位。链头和链尾标识符使用4001 至4018。4019 至4050 为备用,它将来可能作为区号使用,也可能作为链头标识符使用,还可能做其他应用。
如此设置,区位码的编码空间是18 万。区号与位号处于不同的值段,仅从组元的数值即可判断它是区号,还是位号,或者是其他。
本文中,如果没有特殊声明,字符编码的码值用16 进制数字表示。1 个字节用2 个16 进制数字表示,1 个组元用3 个16 进制数字表示。
例如,以下字符的区位码分别是,汉字“岱”为“FFE 6E9”(十进制4094 1769),“山”为“FFF 9CB”(4095 2507),希腊字母“ω”为“FD4 300”(4052 768),日文平假名“は”为“FE6 125”(4070 293),英文字母“F”为“FFF 047”(4095 71)。
区位码码长都是2 个组元,长度等价3 个字节。这些字符在Unicode 码中,码长都是2 个字节,虽然郭码的区位码保证了每个字符都有独立编码,但是它的编码效率比Unicode 码低了很多。
为提高各种文字的编码效率,郭码要对它们做“量体裁衣”式的编码。
郭码根据各种文字所包含字符数量的多少将全世界的文字归入三个字符集:大字符集、中字符集、小字符集。
大字符集包括10 万个中国汉字。
一种文字所含字符数量数以千计的就归入中字符集,它包括朝鲜文(韩文)、藏文、彝文、日文。
小字符集中文字包括拉丁系列、西里尔系列、希腊文、阿拉伯系列、天成文等多种拼音文字,每种文字字母的数量是几十个或一二百个。
对不同的字符集,郭码开发了不同的编码方法。
“缺省原理”的意思是在一定条件下,对一些众所周知的或者事先已有约定的信息进行省略,受众对其给予默认,不影响他们对全部信息的完整理解。
例如广播电台报道新当选政协委员的名单,每位委员的完整信息包括三部分:姓名、性别、民族。因为在中国,大部分的政协委员是男性,大部分的政协委员是汉族,这已是众所周知的,“男”“汉族”在电台广播时就给省略了。实际广播时是“李瑞环、陈慕华、女、阿布都热西提、维吾尔族”。听众知道李瑞环是男性、汉族,陈慕华是汉族,阿布都热西提是男性。
郭码特别设定4095 区为“特区”,该区的字符编码可以只用位号,不用区号,区号被缺省。与郭码配套的文字处理软件依序审视郭码文字文件中的各个组元,若遇到某个位号前面没有区号(也没有链头),就认定它是4095 区的。
大字符集中是中国汉字,郭码设定4095 区至4071 区(FFF 区至FE7 区)为中国汉字占用。
信息论的信源编码部分有个“变长码原理”,其意思是,对一个集合中的各个对象编码,那些使用频度比较高的对象用短码,那些使用频度比较低的对象用长码,如此操作可使总体的平均码长最短,也就是编码效率最高。
中国汉字编码的国家标准有GB2312-80[3]和GB18030—2000,后者兼容前者。
GB2312-80 中包括6763 个汉字,其中“一级汉字”3755 个,是常用的汉字,“二级汉字”3008个,是次常用的汉字。“一级汉字”的范围,从“啊”(B0 A1)到“座”(D7 F9)。
中国汉字很多,它们的使用频度相差悬殊。统计资料显示,“一级汉字”的使用频度占总体的99%以上[4],也就是说,其余9 万多汉字的使用频度还不到总体的1%。
郭码将“一级汉字”全部放入4095 区,“二级汉字”中少量的使用频度较高的汉字和汉文常用的标点符号也放入该区。
英文字符(ASCII 字符)本属于“小字符集”,因为在国际交流中使用比较多,作为特例,也将它们放入4095 区。
利用“缺省原理”,在生成郭码文字文件时,4095 区内的字符使用“缺省方式编码”,即只使用位号编码,码长是1 个组元(二进制的12 位)。
根据信源编码理论,汉字的平均编码长度约为
12×0.99+24×0.01=12.12 (二进制的位)
国家标准GB18030—2000 中汉字的平均码长约为二进制的16 位多一点,4 字节编码汉字的使用频度非常低,它们对平均码长影响很小。
从以上数据可以看出郭码的“缺省方式编码”比ANSI 体系的中国国家标准的汉字的平均码长要短,编码效率更高,大约提高了30﹪。
本文中所举例子,都使用纯文本文件(txt),这样便于比较编码效率的高低。
例1 杜甫的《望岳》诗『岱宗夫如何,齐鲁青未了。造化钟神秀,阴阳割昏晓。荡胸生层云,决眦入归鸟。会当凌绝顶,一览众山小。』 48 个字符。
使用GB18030—2000 编码是96 个字节:
E1 B7 D7 DA B7 F2 C8 E7 BA CE A3 AC C6 EB C2 B3 C7 E0 CE B4 C1CB A1 A3 D4 EC BB AF D6 D3 C9 F1 D0 E3 A3 AC D2 F5 D1 F4 B8 EE BB E8 CF FE A1 A3 B5 B4 D0 D8 C9 FA B2 E3 D4 C6 A3 AC BE F6 ED F6 C8 EB B9 E9 C4 F1 A1 A3 BB E1 B5 B1 C1 E8 BE F8 B6 A5 A3 AC D2 BB C0 C0 D6 DA C9 BD D0 A1 A1 A3
每个汉字和标点符号的码长都是2 个字节,仅列出第一句的编码解释:
E1 B7 岱 D7 DA 宗 B7 F2 夫 C8 E7 如 BA CE 何A3 AC,C6 EB 齐 C2 B3 鲁 C7 E0 青 CE B4 未 C1 CB 了 A1 A3。
郭码的缺省方式编码是75 个字节:
FF E6 E9 F0 C3 64 99 74 5A F4 78 DF 72 F9 32 B9 86 E9 F2 EE 04 49 9E A7 9F FC 83 F4 7D 51 CF 23 BE 4D 2C 40 F2 E2 6A C7 8A 08 17 FD DE F4 75 FA FF EB 90 99 B4 17 82 9F 2E 4C B2 67 70 65 FC 2B 9F 47 D1 76 80 EA E9 CB C4 1F 2E
编码解释:
FFE 6E9 岱 F0C 宗 364 夫 997 如 45A 何 F47,8DF 齐 72F 鲁 932 青 B98 未 6E9 了 F2E。E04 造499 化 EA7 钟 9FF 神 C83 秀 F47,D51 阴 CF2 阳3BE 割 4D2 昏 C40 晓 F2E。26A 荡 C78 胸 A08 生17F 层 DDE 云 F47,5FA 决 FFE B90 眦 99B 入 417归 829 鸟 F2E。4CB 会 267 当 706 凌 5FC 绝 2B9 顶F47,D17 一 680 览 EAE 众 9CB 山 C41 小 F2E。
全诗40个汉字、8个标点符号,只有“岱”和“眦”不在4095 区,它们使用“基本方式”的2 组元编码,分别是“FFE 6E9”和“FFE B90”。
诗中其余的汉字和标点符号都在4095 区中,都是“缺省方式”的1组元编码。文件全长50个组元,即75个字节。一个字符的平均码长是1.5625个字节,即二进制的12.5 位。郭码比GB18030—2000 编码节省了21 个字节,编码效率提高了约28%。因为2 个汉字为非4095 区汉字,它们在本诗中占总字符数量的4.17%,超过了1%,故编码效率的提高没有达到30%。
例2 2008 年,温家宝总理在全国人民代表大会上所做的“政府工作报告”,内容涉及政治、经济、外交、工业、农业、文教卫生等诸多方面,文字使用颇具广泛性。全文共使用汉字22045 个,其中非4095 区汉字4 个,“崛、渎、诿、崛”,占使用汉字总数的0.0001814,即不到万分之二。全文没有使用一个英文字母(用了一些阿拉伯数字)。全文使用GB18030—2000 编码是49952 个字节,用郭码缺省方式编码是38364 个字节,节省了11588 个字节,编码效率提高了30.21%。
阿拉伯数字在GB18030—2000 编码中码长是1个字节,在郭码缺省方式编码中码长是1 个组元,它们在编码效率上是负增长。
由于文件太长,就没有在此列出它的码值及编码解释。
缺省方式编码的单位是组元,生成的郭码文字文件的总长度是整数个组元。组元总数是偶数时,恰好是整数个字节,组元总数是奇数时就不是整数个字节,需要在文件的最后补码半个字节,其值为“0000”(二进制的4 位),此即为“文件补码”。
郭码的汉字编码应用了变长码原理,但是应用此定理的前提是需要知道10 万个汉字中哪些是最常用的、哪些是次常用的、哪些是很少用的。
在此要感谢我国文字方面的科研工作者,他们长期从事有关汉字的基础性的研究工作,对海量的汉字资料做统计、分析,总结出了汉字使用频度列表。“3755 个一级汉字的使用频度在99%以上”就是由此得出。没有它,变长码原理也就无法在郭码的汉字编码中应用[4]。
现在我国使用的文字处理软件执行的是GB18030—2000 标准,它可以打开、编辑ANSI 码和Unicode 码的文件,若用它打开郭码生成的文件,显示的将是一堆乱码。
郭码的正确性需要得到实验的证明。
证明过程如下,笔者编写了一对工具软件A 和B。工具软件A 可以把ANSI 码文字文件(纯文本文件)W1 转译为郭码文字文件W2,工具软件B可以把郭码文件W2 转译为ANSI 码文件(纯文本文件)W3。转译回来的文件W3 与“原始文件”W1完全相同,这就说明郭码文件W2 与ANSI 码文件W1 承载着完全相同的文字信息。
以上例1 中,杜甫的《望岳》诗,使用ANSI码(GB18030—2000)编码(纯文本文件)是96 个字节(W1)。使用工具软件A 可以将其转译为长度为75 个字节的郭码文件W2,具体内容如前所示。使用工具软件B 可以把郭码文件W2 转译为ANSI码文件(纯文本文件)W3,W3 文件与W1 文件完全相同,不仅是一个汉字不能差,而且一个标点符号不能差,一个“空格”、一个“控制符”也都不能差。以此证明75 个字节的郭码文件和96 个字节的ANSI 码文件承载了完全相同的文字信息。
本文所有举例中的郭码文字文件都是由上述方法得来的。以后对各种文字推出多种编码方法,实验证明的方法还是基本相同的,只不过工具软件A和工具软件B 需要不断升级。
文字编码的格式在ANSI 码、Unicode 码与郭码之间相互转换不困难,本文举例的郭码数据大多是从中国标准GB18030—2000 编码转换来的。
缺省方式编码中,英文字符的码长是1 个组元,比Unicode 码的2 个字节短,但是比ANSI 码的1个字节要长。英文字符需要有新的编码方法。
“能否让它们在郭码中不降低编码效率或者让它们少降低编码效率,使它们能够基本维持在ANSI 码中的水平、码长大约是1 个字节”,这是最初的思考。
以ANSI 码和Unicode 码形成的文字文件中是“字节流”,以郭码形成的文字文件中是“组元流”。若英文字符以字节形式存在于郭码中,它就是个“特例”,并且这个特例不应该破坏郭码组元流的基本运作秩序。
计算机程序运行过程中有“中断操作”,一个主进程程序运行过程中遇到“中断语句”时,就要停止主进程程序,改为执行中断程序,在执行完中断程序后再从以前停止的地方继续执行主进程的程序。为了保证主进程程序与中断程序的有序交接,在运行中断程序前要对主进程的“接口参数”做“堆栈式保存”。
汉字文件中间出现一段英文,若按缺省方式编码,每个英文字符是1 组元编码。若将这段英文按ANSI 码的1 字节编码,它与郭码的组元流设计相矛盾。解决办法是将汉字编码(1 组元或者2 组元编码)看作是“主进程的程序”,将英文字符的1字节编码看作是“中断程序”,如此一来,1 字节编码的英文字符和1 组元(或2 组元)编码的汉字就可以“和平共处”了。
欲使1 字节编码的英文字符在郭码中顺利应用,必须要解决这个“中断程序”与“主进程”的过渡、衔接问题。
郭码将汉字编码当作主进程对待,1 字节编码的英文字符视为“中断程序”,将这段连续的英文字符编码置于一个特定的“链”中,称这个链为“第一类符链”。“链”由“链头”“链体”和“链尾”三部分组成。
为了区别于主进程的组元、并限定链的范围,设置“链头标识符”(简称“链头”)和“链尾标识符”(简称“链尾”)。它们各为一个组元,它们的数值与区位码的区号、位号均不相同。链头和链尾之间是“链体”,链体元素的单位是字节,内容是英文字符的1 字节编码。
人们日常写文章时,经常使用“圆括号”,即“()”,链头类似前半个括号“(”,链尾类似后半个括号“)”,链体就是括号里的内容。
郭码的核算单位是组元,现在计算机内运行的程序、数据都以字节为单位,也就是说,二进制12位的组元要“落实”在8 位的字节中。一个组元必定“跨在”两个字节上,会有两种情况,若前一字节中占8 位、在后一字节中占前4 位,称这种形式的“制式”为“84 式”;若前一字节中占后4 位、在后一字节中占8 位,称这种制式为“48 式”。在郭码文字文件中,组元就是以84 式、48 式、84 式、48 式……这样交替排列的。
郭码设定第一类符链的链头值为4001(FA1),链尾值为4002(FA2)。
ANSI 码中一个英文字符的编码全部在一个字节里,称其为“08 式”。在郭码的第一类符链中,它还有另一种存在形式,8 位编码分处于两个字节中,在前一字节中占后4 位,后一字节中占前4 位,称其为“44 式”。当链头是48 式时,其后面的英文字符编码都是08 式;当链头是84 式时,其后面的英文字符编码都是44 式。
为了引入符链后,不打乱郭码组元流的秩序,符链的总长度必须是整数个组元。因链头、链尾各是一个组元,所以,链体的总长度就必须是整数个组元。
链体中元素的单位是字节,并且连续出现的英文字符的数量L 是不确定的,因此就需要对L 进行分类处理。为保障链体长度成为整数个组元,需要酌情增加“链内补码”。
L 的数量只有三类情况,第一类,L 为“3N 型”;第二类,L 为“(3N+1)型”;第三类,L 为“(3N+2)型”;N 为正整数。
第一类,3N 个英文字符的ANSI 编码是3N 个字节,3 个字节恰好是2 个组元,3N 个字节就是2N 个组元,整数个组元不需要补码。链体为2N 个组元,偶数个组元。
第二类,根据前一结论,(3N+1)个字节是2N 个组元再加1 个字节,这个字节要“扩展为组元”需要加补二进制的4 位,可以是“0000”(二进制),此即为“链内补码”。补码后链体为(2N+1)个组元,奇数个组元。
第三类,(3N+2)个字节是2N 个组元再加2个字节,这2 个字节要“扩展为2 个组元”,需要加补二进制的8 位,即1 个字节。该字节的值设定为129(16 进制的81),如此赋值是为了与英文字符ANSI 编码的值(0~127)相区别。补码后链体为(2N+2)个组元,偶数个组元。
链体经过上述处理,再配上链头4001(FA1)、链尾4002(FA2),连续英文字符的编码就形成为第一类符链编码。
链头、链尾、链内补码,它们本身不是所要传输的英文字符的信息,而是构成第一类符链必须要付出的额外开销。若链体三类情况出现的概率相同,平均每个符链补码4 位,再考虑链头、链尾需要占用24 位,第一类符链付出的“平均成本”是28 位,3.5个字节。这个“平均成本”与链体内包含的英文字符的数量无关。
理论上讲,一个英文字符也可以生成第一类符链,但“经济上”不合算。若不生成符链,它的码长是1 个组元,1.5 个字节。若生成符链,链头、链尾加上链内补码4 位共需3 个组元,4.5 个字节。
8 个连续的英文字符不生成符链时,码长是8个组元,12 个字节。若生成符链,“8 个”属于“3N+2型”,需链内补码8 位,符链总长度也是12 个字节。
当连续的英文字符达到9 个时,不生成符链码长是9 个组元,13.5 个字节。“9 个”属于“3N 型”,链体不需要链内补码,符链长度为8 个组元,12 个字节,生成符链转为“赢利”。这也就是郭码生成第一类符链的起始标准。连续不足9 个的英文字符不生成第一类符链,采用缺省方式编码。
出现英文字符时,生成还是不生成符链,由文字处理软件来决定。当然,此文字处理软件要比现在使用的文字处理软件复杂,可称为“智能型文字处理软件”。
举例说明第一类符链编码。以下的ANSI 码就是GB18030—2000 标准的编码。
例3 短文『小二黑给小芹发了条短信“I love you”,小芹收到了但是没看懂,因为她没学过英文。』46 个字符。
ANSI 码的编码80 个字节(略)。
郭码缺省方式编码69 个字节:
C4 13 12 46 63 C8 C4 19 2D 31 46 E9 B1 D2 E0 C6 5F 37 04 A0 21 06 D0 70 07 70 66 02 10 7A 07 00 76 F3 8F 47 C4 19 2D A4 12 73 6E 92 61 A3 37 95 61 62 C2 F4 7D 4E B8 EA C7 79 5C A5 42 BD 5C BA 8F 2E 00 E0 0B
文中英文部分(第19 个至第33 个字节)编码解释:04 A I 021 空格 06D l 070o 077 v 066 e 021空格 07A y 070 o 076 u
第一类符链编码(缺省方式编码自动生效)68个字节:
C4 13 12 46 63 C8 C4 19 2D 31 46 E9 B1 D2 E0 C6 5F 37 FA 14 92 06 C6 F7 66 52 07 96 F7 50 FA 2F 38 F4 7C 41 92 DA 41 27 36 E9 26 1A 33 79 56 16 2C 2F 47 D4 EB 8E AC 77 95 CA 54 2B D5 CB A8 F2 E0 0E 00 B0
编码解释:
C41 小 312 二 466 黑 3C8 给 C41 小 92D 芹 314发 6E9 了 B1D 条2E0 短 C65 信 F37 “ FA1 链头 49 I 20 空格 6C l 6F o 76 v 65 e 20 空格79 y 6Fo 75u 0 链内补码 FA2 链尾 F38 ” F47,C41 小 92D 芹A41 收 273 到 6E9 了 261 但 A33 是 795 没 616 看2C2 懂 F47,D4E 因 B8E 为 AC7 她 795 没 CA5 学42B 过 D5C 英 BA8 文 F2E。00E 控制符 00B 控制符0 文件补码
其中链内补码和文件补码各为二进制的4 位。
在第一类符链中英文字符的码值与ANSI 码中的码值是相同的。
文中英文句子是10 个连续的英文字符(包括2个空格),可以生成符链,链头FA1 为84 式,链尾FA2 为84 式,链体中英文字符的编码均为44 式。第30 个字节“50”是链体的最后一个字节,它的低4 位是链内补码。因为“10 个”属于“(3N+1)型”,应补二进制4 位。
该短文的郭码有符链比无符链少了一个字节,原因就在这句英文。英文字符是10 个,缺省表示方式编码是10 个组元,15 个字节;有符链时符链全长为9 个组元,13.5 个字节。后者比前者少1 个组元,1.5 个字节,但是有半个字节花费在文件的最后,最后的字节“B0”的低4 位是文件补码。
由此例可以看出,生成了第一类符链的郭码比没有符链的郭码,虽然增加了链头、链尾、链内补码、文件补码的开销,但是相比缺省方式编码编码效率还是有所提高。
例4 短文『He said:"That's one small step for a men,one giant leap for mankind."』
ANSI 码编码73 个字节(略)。
郭码的缺省方式编码110 个字节(略)。
郭码第一类符链编码77 个字节:
FA 14 86 52 07 36 16 96 43 A2 02 25 46 86 17 42 77 32 06 F6 E6 52 07 36 D6 16 C6 C2 07 37 46 57 02 06 66 F7 22 06 12 06 D6 56 E2 C2 06 F6 E6 52 06 76 96 16 E7 42 06 C6 56 17 02 06 66 F7 22 06 D6 16 E6 B6 96 E6 42 E2 20 D0 A0 FA 20
编码解释:
FA1 链头48 H 65e 20 空格73 s 61a 69 i 64 d 3A:20 空格22 " 54 T 68 h 61 a 74 t 27 ' 73 s 20 空格6F o 6E n 65 e 20 空格 73 s 6D m 61 a 6C l 6C l 20 空格73 s 74 t 65 e 70 p 20 空格 66 f 6F o 72 r 20 空格 61 a 20 空格 6D m 65 e 6E n 2C,20 空格6 F o 6E n 65 e 20 空格67 g 69 i 61 a 6E n 74 t 20 空格6C l 65 e 61 a 70 p 20 空格66 f 6 F o 72 r 20 空格6D m 61 a 6E n 6B k 69 i 6E n 64 d 2E .22 " 0D 控制符 0A 控制符 0链内补码 FA2 链尾 0 文件补码
本例全部是英文字符,第一类符链编码就是一整个符链。它比ANSI 码多花费了4 个字节,其中链头1.5,链尾1.5,链内补码0.5,文件补码0.5 个字节。显然,英文文件越长第一类符链字符的平均码长越接近1 个字节。
与郭码相配套的文字处理软件解读郭码文字文件时,需要沿组元序列逐个审视每个组元,根据组元的数值做出相应的处理。当遇到链头标识符(如FA1)时,不再逐个审视后面的组元,而是改为向后、在组元序列中搜索链尾标识符(FA2)。找到链尾后,记录下它的位置,链头与链尾之间就是链体。
不同的链式编码,链头数值不同,链体构成不同,处理方法也不同。第一类符链链体元素是字节,逐个字节处理,遇到“链内补码”就跳过去。该链处理完,就从链尾下面一个组元开始,继续沿组元序列逐个审视每个组元。
链体内是英文字符的ANSI 码,其值范围是00至7F。它们跨字节能够形成的最大的二进制12 位的数字是“F7F”,即使考虑链内补码“81”,能够形成的最大数字是“F81”,它们都小于链尾值“FA2”,因此,链体元素不会对搜索链尾构成干扰。
郭码中有多种“链式编码”,针对英文字符的链称为“符链”,针对英文和中国汉字以外文字的链称为“字链”。
中字符集中包括日文、彝文、藏文、朝鲜文(韩文),它们包含的字符都数以千计,都使用“第一类字链”编码。
第一类字链由链头、链体、链尾三部分构成,链头、链尾各为一个组元,链尾值固定为4002(FA2)。链体元素的单位也是组元,全链肯定是整数个组元,因而第一类字链编码不存在链内补码的问题。
因为中字符集内有彝文等数种文字,故第一类字链分为若干组,每组字链对应一种文字。
第1 组字链对应的是日文,日文的平假名、片假名及日文常用汉字放入4070(FE6)区。现代日文中汉字占比越来越少,大量外来词汇使用片假名,如“テレビ”。
第1 组字链的链头为4003(FA3),它与4070区是固定的配对关系。在第1 组字链中,链体的元素就是该日文字符在4070(FE6)区内的位号。
例如,日文平假名“た”的基本方式编码是“FE6 115”,它在第1 组字链链体内时,就只是位号“115”。
如果有2 个连续的日文字符,使用基本方式编码,它们的编码长度为4 个组元;若生成第1 组字链,字链总长度也是4 个组元。当出现连续3 个日文字符时,使用基本方式编码,长度为6 个组元;若生成第1 组字链,字链总长度为5 个组元。所以,连续3 个日文字符就是生成第一类第1 组字链的起始标准。
以后其他链的“起始标准”也如此计算,即链式编码比基本方式编码总码长更短的最少的连续字符个数,就是起始标准。
第一类第2 组字链对应的是彝文,彝文的全部1222 个字符都放入4069(FE5)区,位号是1至1222。第2 组字链的链头是4004(FA4),它与4069 区是固定的配对关系。第2 组字链链体的元素是彝文字符在4069 区中的位号。连续3 个彝文字符就是生成第2 组字链的起始标准[5]。
日文字符已有数种编码方法,日本国国家标准编码(Shift JIS)与GB18030—2000 很相似,同属ANSI 码体系,字符是2 字节编码。
日本标准编码(Shift JIS)36 个字节:
82 BB 82 EA 82 CD 82 BD 82 A2 82 B5 82 BD 82 B1 82 C6 82 C5 82 CD 82 C8 82 A2 82 C5 82 B5 82 E5 82 A4 81 42
每个字符都是2 字节编码,它们的第一个字节的码值都大于“7F”。平假名“”的码值是“82 BD”。
Unicode 码编码38 个字节:
FF FE 5D 30 8C 30 6F 30 5F 30 44 30 57 30 5F 30 53 30 68 30 67 30 6F 30 6A 30 44 30 67 30 57 30 87 30 46 30 02 30
最前面的2 个字节是Unicode 码的标识符,每个日文字符都是2 字节编码,“”的码值是“5F 30”。
郭码第一类第1 组字链编码30 个字节:
FA 31 13 14 21 25 11 50 FA 10 D1 15 10 91 1E 11 D1 25 12 00 FA 11 D1 0D 13 D0 FC 08 2F A2
编码解释:
链头、链尾2 个组元,字符编码18 个组元,共20 个组元,即30 个字节。
日本标准编码(Shift JIS)48 个字节(略)。
第一类第1 组字链编码39 个字节:
FA 31 45 11 51 05 10 D1 25 19 12 09 1A F1 25 15 B1 AF 13 D1 40 13 61 10 10 11 0D 0F 91 1E 1F E1 0E 13 41 0F 08 3F A2
编码解释:
本例郭码的基本方式编码,需要48 个组元。每个字符的编码由区号和位号组成,24 个字符的编码里就有24 个相同的区号(FE6)。
第一类字链的第1组字链编码,链头4003(FA3)与区号4070(FE6)是固定的配对关系,即由链头值就可知区号。1 个链头就代替了24 个区号,链体内只有位号,这是链式编码既包括了区位码的全部信息又能够提高编码效率的基本原理之一。
第1 组字链日文字符的平均码长与一个链内字符数量的多少有密切关系,字符数量越多,它们的平均码长就越接近(大于)二进制的12 位。如果日文字符连续有100 个,它们的平均码长是1.53 个字节,即二进制的12.24 位,编码效率比日本标准编码提高约30.72%。
第一类字链的第2 组字链,彝文的编码情况与日文类似。
本文中称英文、俄文、希腊文等拼音文字为“简单拼音文字”,它们的字母在生成文字文件时在一维空间内即水平方向上顺序排列。朝鲜文、藏文也是拼音文字,但是它们的字母组成“字”时,是在二维空间内、即垂直方向和水平方向上组合排列,情况复杂,故称它们为“复杂拼音文字”。
第一类字链的第3 组字链对应的是藏文。
藏文有字母30 多个,由字母组成藏字比较复杂,首先几个字母上下排列组成“垂直预组件”(俗称“字丁”),然后若干个字丁再在水平方向上排列组成藏字。仅有藏文字母编码难于表达藏字的信息(使用“组合式编码方法”效率非常低),比较可行的方法是对字丁编码。有了字丁的编码,它们就可以象英文字母组成单词一样在水平方向上排列构成藏字的编码。
藏文有字母及字丁等字符共7430 个[6][7][8],需要放在两个区中。
设定藏文字符编码放在4068 (FE4)区和4067(FE3)区中,这两个区是藏文专属区,其中,4068区为“基本区”,4067 区为“辅助区”。藏文字符中使用频度最高的3999 个字符放入4068 区,位号为1 至3999;使用频度较低的3431 个字符放入4067 区,位号为1 至3431。位号4000(FA0)不做位号编码使用,而是特别设计它为“假区号”,即在链内作为“区号”使用,专指辅助区4067 区。
第3 组字链的链头是4005(FA5),链尾仍是4002(FA2)。链头4005 与区号4068 是固定的配对关系。
郭码第一类第3 组字链编码时,基本区字符的码值就是其在该区中的位号,码长1 个组元;辅助区字符码值由假区号4000(FA0)与该字符在辅助区中的位号共同组成,码长为2 个组元。
如果不设置“假区号”,第3 组字链中只能包括基本区的字符,辅助区的藏文字符就得使用基本方式编码,码长为2 个组元。藏文使用第3 组字链编码遇到一个4067 区的字符时,原字链就得结束,加装链尾FA2。再对4067 区的这个字符做基本方式编码。后面又是基本区的字符,再开始生成新的第3 组字链,加装链头FA5……如此“加装链尾”“加装链头”,增加了链头、链尾的开销。
有了“假区号”,虽然辅助区的藏文字符在字链中仍然是2 组元编码,但是只要使用的是这7430个之内的藏文字符,一段藏文文章编码就是一整个字链,避免了字链的多次“断裂”,整体编码效率相对更高些。
中国向国际标准化组织申请藏文编码在Unicode 码中的空间,历经多次申诉与谈判,1997年国际标准化组织在基本平面内只批给藏文在0F行的256 个码位。无奈,藏文编码标准将1536 个常用字丁放在了基本平面的“用户自定义区”中,为2 字节编码,其他5702 个次常用字丁只能是4字节编码。由于Unicode 码各种文字的用户都可以使用“用户自定义区”,这些编码是不独立的,用户间相互冲突的风险很大。
郭码不仅使原来1536 个2 字节编码的字丁改为1 组元编码,而且2463(3999-1536)个原来4字节编码的字丁也改为1 组元编码。藏文编码更高效,并且稳定可靠。
第一类字链的第4 组字链对应的是朝鲜文(韩文),编码方式与藏文类似。
Unicode 码(ISO/IEC 10646—93)基本平面中,有朝鲜文字母及谚字6990 个。它们放入4066 (FE2)区和4065(FE1) 区,这两个区是朝鲜文专属区,其中,4066 区为“基本区”,4065 区为“辅助区”。朝鲜文字符中使用频度最高的3999 个放入4066 区,位号为1 至3999;使用频度较低的2991 个字符放入4065 区,位号为1 至2991。位号4000 不做位号编码使用,设定为“假区号”,用法同前面第3 组。
第4 组字链的链头是4006(FA6),链尾仍是4002(FA2)。链头4006 与区号4066 是固定的配对关系。
郭码的链式编码受到“旅游团”的启发。
近些年来,随着旅游人数的不断增加,有人研究其中的规律,发现了商机,成立了旅行社,搞起了“组团游”。
旅行社把有相同目的地、相同时间出游的个人召集起来,组成一个旅行团。该团是地点、日程固定,机票、景点门票、食宿完全由旅行社给办理,参团的游客只需按旅行社的“菜单”缴费即可。
组团游不仅人数多(旅行团有最低人数限制),而且计划性强,便于民航事先调度安排,从而提高飞机上座率、降低运营成本,所以民航愿意给它打折。酒店、景区情况也类似。因此,组团游旅行社能赚钱,游客能省心省钱,民航、酒店、景区能多赢利,形成了一个“多赢”的局面。
相比之下,“个人游”(散客)随意性强,对民航、酒店而言有太多不可预知的因素,要承担更多的风险,故它们对个人游的收费定价较高。
ANSI 码和Unicode 码把各种文字的字符看作许多互不相关的个体,当作“散客”对待,字符编码需付出较高的代价(编码较长)。郭码中的“基本方式编码”也是如此。
笔者注意并研究了各国文字的使用情况,发现了其中的规律,搞起了文字编码的“组团游”——链式编码。组团游和链式编码都发挥了“团队效应”。
世界上各种文字,笔画多少、字符数量等千差万别,但它们都有共同的功能、有共同的规律。语言和文字都是人们传递信息的工具。受到发言者(作者)和听众(读者)所掌握的语言(文字)能力的限制,为了交流的顺畅,大多数情况下是使用同一种语言(同一种文字)来表达的。
人们使用某种文字写文章,是为了表达想法,传递信息。这需要大量同种文字的字符相继连接、构成“词”、组成“句子”、再形成文章才能实现。因此,同一种文字的各个字符经常是以“团队”形式出现的,这是文字使用的普遍规律。
郭码的策略是,尽量搞字符的“组团游”(链式编码),实在不能“组团”的,再搞“个人游”(基本方式编码)。
小字符集中的文字是与英文情况类似的拼音文字,既然英文字符可以通过第一类符链编码使得每个字符的平均码长接近一个字节,那么小字符集其他的拼音文字也可以通过链式编码取得相同的效果。
用于小字符集文字编码的链称为“第二类字链”。
由于小字符集包括的文字种类很多,就将它们分为5 个组。
第1 组包括拉丁系的文字,有法文、德文、西班牙文等。还有中国的壮文、苗文、瑶文。
第2 组包括阿拉伯系的文字,有阿拉伯文、波斯文、乌尔都文、哈萨克文、维吾尔文、柯尔克孜文等。
第3 组包括印度的文字,有天成文(梵文)、孟加拉文、锡克文、古吉拉特文、奥里亚文、泰米尔文、泰卢固文、卡纳达文、德拉维文等。
第4 组包括西里尔系文字,有俄文、乌克兰文、塞尔维亚文、保加利亚文、蒙古文(蒙古国)、马其顿文等。还有希腊文、希伯来文。
第5 组包括蒙古文(中国)、傣文、锡伯文、泰文、高棉文、僧加罗文等。
第二类字链包括5 组编码,各组的链头值依次是4007(FA7)、4008(FA8)、4009 (FA9)、4010(FAA)、4011(FAB),它们固定配对的区号,依次是4060(FDC)、4059(FDB)、4058(FDA)、4057(FD9)、4056(FD8)。
链尾值都是4002(FA2)。链体元素单位是字节,其第一个字节是“基本段的段号”,以后的字节是字符编码及链内补码。
每一个区划分为16 个“段”,一个段包容一种或数种拼音文字。每个段长度为239 个位(“位号”的位)。每个段的起始位置是“段地址”,16 个段的段地址依次为1,240,479,718,957,1196,1435,1674,1913,2152,2391,2630,2869,3108,3347,3586。
16 个段的“段号”依次为255,254,253,252,251,249,248,247,246,245,244,243,242,241,240,239。“250”(16 进制的FA)不在其中。
段内的“子位号”是字符的位号与其所在段的段地址之差,其值分别为0,1,2,…,161,163,164,…,237,238。每段空闲一个码位,“162”(A2)值不使用,只使用238 个子位号。例如,段号是248(按序是第7 段,其段地址为1435),子位号为200,其位号就是1635。
段号与段地址是固定的对应关系,由于许多段地址数值大于255,无法用一个字节表示,故而用段号“代表”段地址的信息。
段号中没有250(FA),子位号中没有162(A2),是为了避免在链体中形成值为“FA2”的“组元”,以保证对链尾(FA2)的准确搜索。
链体总长度必须是整数个组元,链内补码与第一类符链的链内补码相同,三种类型分别补二进制的0 位(不用补码)、4 位和8 位,补4 位时补“0000”(二进制),补8 位时补“1111 1010”(16 进制的FA,10 进制的250)。由于子位号的最大值是238(EE),故补码“FA”不会与子位号混淆,又因为补码“FA”已在链体的最后,它不会影响对链尾的准确搜索。
一组链内只能有一个段是“基本段”,同区其余的段作为“辅助段”,链体的第一个字节就是基本段的段号。基本段内字符的编码用子位号表示(1字节),辅助段字符编码用辅助段的段号和子位号表示(2 字节)。如此设计,使得一个区(16 个段)内的字符均可在一个链内。因此,同一种文字的字符应尽可能放在同一个段内。如果一个段内放不下,要将该种字符中使用频度最高的238 个字符放在同一段(基本段)内,其余字符放在同区其他段中。
一组字链中,哪个段是基本段并不是一成不变的,可以由用户选择。例如,俄文用户就选择含俄文字符的段为基本段。与郭码配套的文字处理软件应该给用户提供这种功能。
因为第二类字链的各组链头与区号是固定配对关系,所以由链头值就可知区号;由链体内的段号可查出段地址,段地址与子位号之和就是该字符的位号。所以说,第二类字链编码是间接给出区号信息,间接给出位号信息。
以下以俄文和希腊文为例。
俄文字母的编码在4057 区,将其大小写66 个字母的编码放在该区的第3 段(段号是253),其段地址为479,这些字母的子位号是从0 到65(先大写后小写)。俄文中使用的符号“控制符(0A)”“控制符(0D)”“间隔符(空格)”“-”“,”“.”等6 个符号也放在该段中,它们的子位号为66 到71。这些字母和符号在4057 区中的位号是从479到550。
与4057 区配对的第二类第4 组字链的链头为4010(FAA)。
例7 短文『 小芹给二黑邮件“Я люблю тебя”,二黑答“Очень хорошо”,他学过俄文。』46 个字符。
郭码第二类第4 组字链编码,69 个字节:
C4 19 2D 3C 83 12 46 6D 84 54 6F 37 FA AF D2 04 42 D4 02 22 D4 04 43 42 62 24 10 FA 2F 38 F4 73 12 46 62 48 F3 7F AA FD 0F 39 26 2F 3E 44 37 30 32 30 3A 30 0F A2 F3 8F 47 AC 5C A5 42 B3 01 BA 8F 2E 00 E0 0B
编码解释:
C41 小 92D 芹 3C8 给 312 二 466 黑 D84 邮 546件F37“ FAA 链头(4010) FD 基本段段号(253)20Я 44 空格 2Dл 40ю 22б 2Dл 40ю 44 空格 34т 26е 22б 41я 0 链内补码 FA2 链尾 F38” F47,312 二 466 黑 248 答 F37“ FAA 链头 FD 基本段段号 0FО 39ч 26е 2Fн 3Eь 44 空格 37х 30о 32р 30о 3Aш 30о 0 链内补码 FA2 链尾 F38” F47,AC5 他CA5 学 42B 过 301 俄 BA8 文 F2E。00E 控制符(0D)00B 控制符(0A)
第4 组字链链体的第一个字节FD(253)是基本段的段号,其后面是俄文字符的1 字节编码,是它们在253 段内的子位号。例句中的两句俄文恰好都是12 个字符(含空格),它们的前面都多了一个字节的“基本段的段号”,就成为了“(3N+1)型”,需要链内补码4 位。
例8 希腊短文『εγω ειμι ο διδασκαλοσ.』24 个字符。
在GB18030—2000 中,A6 区的A1 到B8、C1到D8 是大小写共48 个希腊字母。这些希腊字母的编码放在4057 区的第4 段(段号是252),子位号从0 到47,位号从718 到765。
俄文中使用的符号,“空格”“-”“,”等6 个符号仍然在253 段,它们的位号也不变。
第4 组字链编码35 个字节:
FA AF C1 C1 A2 FF D4 41 C2 02 32 0F D4 42 6F D4 41 B2 01 B1 82 92 11 82 22 62 9F D4 7F D4 3F D4 20 FA 20
编码解释:
FAA 链头 FC 基本段号(252)1Cε1Aγ2Fω FD 辅助段号(253)44 空格1Cε20ι 23μ 20ι FD 辅助段号(253)44 空格 26ο FD 辅助段号(253)44空格 1Bδ 20ι1Bδ 18α 29σ 21κ 18α 22λ 26ο 29σ FD辅助段号(253)47.FD 辅助段号(253)43 控制符(0D) FD 辅助段号(253) 42 控制符(0A) 0 链内补码 FA2 链尾 0 文件补码
本文有18 个希腊字母(每个字母为1 字节编码)、6 个符号(每个符号为2 个字节编码),基本段号(FC)1 个字节,共31 个字节,属于“(3N+1)型”,链内补码二进制4 位。加上链头、链尾3 个字节共34.5 个字节,最后文件补码二进制4 位,总共35 个字节。
希腊字母编码在252段,6个符号编码在253段,该字链的基本段是252 段。253 段是辅助段,每个符号的编码由辅助段号FD 和子位号组成。如果6个符号也在252 段内编码(253 段的编码仍然保留),那么本链中的6 个辅助段号就可以省掉,编码效率会更高。
由以上2 例可以看出,链内同种字符数量增多时,它们的平均码长就接近1 个字节。
郭码的4060 到4056 区有80 个段,基本上可以将Unicode 码基本平面内的小字符集的字符全部收入囊中,如果5 个区不够用,还可以再增加。
英文字符通过第一类符链编码提高了编码效率,一个字符的平均码长接近1 个字节,但还是比ANSI 码的长。欲再提高英文字符的编码效率,就要改变字符编码的单位,充分利用变长码原理和缺省原理。此链就是第二类符链。
第二类符链仍然由3 部分组成,链头4013(FAD),链体,链尾4002(FA2),链体元素的单位是“半组元”。
“半组元”是新创建的单位,其长度是组元的一半,即二进制的6 位,其能表示的数字是从0 到63,其容量为64,是组元容量的64 分之一,是字节容量的四分之一。
半组元是二进制的6 位,用16 进制数字表示不方便。为此,引入“4 进制数字”,1 位4 进制数字等效代替2 位二进制的数字,2 位4 进制数字等价1 位16 进制的数字。例如,与16 进制数字“1,6,9,C”对应的4 进制数字是“01,12,21,30”。
半组元可以用3 位4 进制数字表示,如“63”(10进制)可用4 进制数字“333”表示。组元可以用6位4 进制数字表示。
根据第二类符链编码的需要,设置两个数组,它们的大小均与半组元的容量相同(64)。第一个为“基本数组”,第二个为“辅助数组”。将ASCII 字符全部放到这两个数组中,重新编码,各组中的码长是二进制的6 位。使用频度高的字符放入“基本数组”,使用频度低的放入“辅助数组”。
从互联网上查到英文字母的使用频度列表,据此安排,基本数组中的字符有10 个阿拉伯数字、基本拉丁字母大小写44 个(去除J j Q q X x Z z)和8 个符号“空格”“,”“.”“-”“"”“ '”(ANSI码的20,2C,2E,2D,22,27)、控制符0D、控制符0A。它们的编码是从0 到61。其余字符(包括J j Q q X x Z z)放入辅助数组,编码也是从0 到61。
在链体中出现基本数组的字符时,直接用它组内的6 位码值;出现辅助数组的字符时,要在其码值前面加上“63”(4 进制的“333”),它的作用是表示其后面的6 位码值是辅助数组的。实际上,在第二类符链中,基本数组中字符是6 位编码(1个“半组元”),辅助数组中的字符是12 位编码(2个“半组元”)。
基本数组内字符编码排序如下(4进制数表示):
000 空格001 1 002 2 003 3 010 4 011 5 012 6 013 7 020 8 021 9 022 0 023 A 030 B 031 C 032 D 033 E 100 F 101 G 102 H 103 I 110 K 111 L 112 M 113 N 120 O 121 P 122 R 123 S 130 T 131 U 132 V 133 W 200 Y 201 a 202 b 203 c 210 d 211 e 212 f 213 g 220 h 221 i 222 k 223 l 230 m 231 n 232 o 233 p 300 r 301 s 302 t 303 u 310 v 311 w 312 y 313,320 .321 -322 "323 (控制符0D) 330 (控制符0A) 331 '
由于第二类符链链体中英文字符的总量是不确定的,其中有多少个是“辅助数组”的字符也不确定,为保证第二类符链的总长度是整数个组元,就要考虑链内补码。因为链体元素单位是半组元,链体内字符编码的半组元个数是偶数时,恰好是整数个组元,不需要补码;字符编码的半组元个数是奇数时,需要链内补码1 个“半组元”,其值为“62”(4 进制的“332”)。
链尾“FA2”是一个组元,它的4 进制表示是“33 22 02”。若将一个组元分成前后两个“半组元”来看,“前半个组元”是“332”,“后半个组元”是“202”。因为“62”(4 进制的“332”)不作为字符编码使用,链体内的字符编码中不可能出现“332”,故链体内字符编码不影响对链尾的搜索。
再者,若链体内编码的半组元从前往后排序(1,2,3,…),序号为奇数的是“前半个组元”,序号为偶数的是“后半个组元”。当链体内字符编码的半组元个数为奇数时,最后一个“半组元”肯定是“前半个组元”,“332”只能补在“后半个组元”中,故链内补码不会影响对链尾的搜索。
第二类符链中英文字符的平均码长由第二类符链的总长度(以二进制的“位”为单位)除以所含英文字符的数量得来。链内的英文字符达到16 个时(按全部为基本数组的字符考虑),第二类符链的总长度是120 位,一个字符的平均码长是7.5 位,少于ANSI 码的8 位。链内的英文字符数量越多,此一优势越显著。
例9 短文『He said:"That's one small step for a men,one giant leap for mankind."』
ANSI 码编码73 个字节(略)。
郭码的第二类符链编码59 个字节(16 进制):
FA D4 A5 03 18 69 93 F2 80 E9 CA 21 CB DC 40 BA D9 40 C6 C8 6B AC 0C 72 96 F0 26 BB 00 21 02 C9 6D DC 0B AD 94 09 E9 86 DC 80 AE 58 6F 02 6B B0 02 C8 6D AA 9B 64 E3 AE FC FA 20
郭码的第二类符链编码(4 进制):
3322 3110 2211 0003 0120 1221 2103 3302 2000 3221 3022 0201 3023 3130 1000 2322 3121 1000 3012 3020 1223 2230 0030 1302 2112 3300 0212 2323 0000 0201 0002 3021 1231 3130 0023 2231 2110 0021 3221 2012 3130 2000 2232 1120 1233 0002 1223 2300 0002 3020 1231 2222 2123 1210 3203 2232 3330 3322 0200
编码解释:
332 231 链头102 H 211 e 000 空格 301 s 201 a 221 i 210 d 333 022 :000 空格322 " 130T 220 h 201a 302 t 331 ' 301s 000 空格232 o 231 n 211 e 000 空格 301 s 230 m 201 a 223 l 223 l 000 空格301 s 302 t 211 e233 p 000 空格212 f 232 o 300 r 000 空格201 a 000 空格 230 m 211 e 231 n 313,000 空格232 o 231 n 211 e 000 空格 213 g 221 i 201 a 231 n 302 t 000 空格223 l 211 e 201 a 233 p 000 空格 212 f 232 o 300 r 000 空格230 m 201a 231 n 222 k 221 i 231 n 210 d 320. 322 " 323 (控制符0D) 330 (控制符0A)332 202 链尾00 文件补码
全文有英文字符73个,只有1个字符(冒号“:”)属于辅助数组,其编码“333 022”为2 个“半组元”。其余字符都属于基本数组,码长为1 个“半组元”。
链体内有“半组元”74 个,不需要链内补码。全链共39 个组元(58.5 个字节),为奇数,需要文件补码4 位。全文编码长59 个字节。
第二类符链编码使得本例中一个英文字符的平均码长为6.4658 位,编码效率比ANSI 码提高23.73%。
例10 一篇宣言
ANSI 码文件长9655 个字节(略)。
郭码第二类符链编码文件长7313 个字节(略)。
9655 个字符中,“辅助数组”的有90 个。加上链内补码1 个“半组元”,链体共有9746 个“半组元”。再加上链头、链尾2 个组元,第二类符链总共4875 个组元,为奇数,故在最后“文件补码”4位(二进制)。文件长7313 个字节,比ANSI 码文件节省了2342 个字节。
郭码英文字符平均码长为6.0595 位,编码效率比ANSI 码提高了32.03%。
本例中,辅助数组中字符使用频度为0.9322%,不足百分之一,经过对数万字符的英文资料测试,结果基本相同。据此估算,链内的英文字符数量达到200 个以上,第二类符链编码效率就会比ANSI码提高约30%。
本节的内容曾经在《通信技术》2016 年第一期上发表,题目是“一种提高英文编码效率的编码方法”。
小字符集中拼音文字的情况与英文相似,它们的编码效率也可以高于ANSI 码。为此,推出郭码的第三类字链编码。
第三类字链再次设定小字符集文字的编码区域(与第二类字链对应的区域不同),各组字符依次在4055、4054、4053、4052、4051 区,与这些区固定配对的第三类各组字链的链头值,依次为4014(FAE)、4015(FAF)、4016(FB0)、4017(FB1)、4018(FB2)。链尾值仍然是4002(FA2),链体内元素的单位是“半组元”。
第三类字链对应的区,每一个区划分为16 个段,每段长度为240 个位(区位码的“位”)。每段的起始位是“段地址”,16 个段的段地址依次为1,241,481,721,961,1201,1441,1681,1921,2161,2401,2641,2881,3121,3361,3601。16个段的“段号”依次为1,2,…,16。区内16 个段之外的空间(3841 至4000)留作备用。
段内的“子位号”是字符的位号与段地址之差,各段“子位号”的值是从0 到239。每个段等分为4 个班组,从前往后依次为基本班组、辅助1班组、辅助2 班组、辅助3 班组。每个班组在段内的起始位是“班组地址”,各“班组地址”依次为0,60,120,180。各个班组内字符的子位号与班组地址之差即是字符的“班组内编码”(二进制的6 位),其值为0,1,2,…,59。辅助1 班组、辅助2 班组、辅助3 班组的“班组代号”依次为63,61,60,基本班组的“班组代号”缺省。
小字符集中的一种文字放在一个段内,该文字中使用频度最高的60个字符放入该段的基本班组,其余的字符放入各辅助班组。若该种文字的字符数超过240 个,余下的、使用频度最低的字符放到本区16 个段之外的空间(3841 至4000)或其他段中,它们不能进入该种文字的链,而只能用“基本方式”编码。
链体内的第一个元素是该种文字所在段的段号,其后是该段内各字符的编码,最后一个元素有可能是“链内补码”。基本班组的字符编码只用“班组内编码”,“班组代号”缺省,码长是1 个“半组元”。辅助班组的字符编码包括“班组代号”和“班组内编码”两部分,码长是2 个“半组元”。
由于第三类字链中字符的数量是不确定的,其中有多少个“辅助班组”的字符也不确定,为保证第三类字链的总长度是整数个组元,就要考虑链内补码。因为链体元素的单位是半组元,链体内半组元的总数(包括段号和字符编码)是偶数时,恰好是整数个组元,不需要补码;半组元总数是奇数时,需补码1 个“半组元”,其值为“62”(十进制)。
字符的第三类字链编码与其基本方式编码有特殊关系。由链头的值可知该字符所在的区号;由段号可查到段地址,由班组代号可查到班组地址,班组内编码、班组地址、段地址,三者之和就是该字符的位号。“第三类字链”编码包含了区位码的全部信息。
以俄文为例说明第三类字链的应用。
在第二类字链编码举俄文例子时,使用的是中国标准GB18030—2000,每个字母码长是2 个字节。现在使用俄罗斯的国家标准“西里尔文windows”,它也属于ANSI 码体系,西里尔文字母及符号占用首字节的后半段(128 到255),是1字节编码。中国标准GB18030—2000 和俄罗斯的国家标准“西里尔文windows”同属ANSI 体系,它们不可以在同一纯文本文件中使用。
设俄文字母及部分ASCII 字符编码在4052 区的第3 段,固定配对的第三类第4 组字链的链头为4017(FB1)。
由于研究条件所限,在互联网上没有找到俄文字母使用频度的资料,就自己编写程序,对数万字符的俄文文章进行统计,得出俄文字符使用频度的数据,做出了以下安排。
基本班组内放使用频度最高的60 个字符,它们是西里尔字母53 个:
其余的俄文字母和ASCII 字符放入辅助1 班组、辅助2 班组、辅助3 班组。
例11 短文『Факты -упрямая вещь.』
俄罗斯国家标准编码23 个字节:
D4 E0 EA F2 FB 20 96 20 F3 EF F0 FF EC E0 FF 20 E2 E5 F9 FC 2E 0D 0A
第三类第4 组字链编码23 个字节(16 进制):
FB 10 FF 01 88 AA C7 7F CD DE B9 E8 D2 46 34 DD A7 70 CB BD B5 FA 20
4 进制数表示:
3323 0100 3333 0001 2020 2222 3013 1333 3031 3132 2321 3220 3102 1012 0310 3131 2213 1300 3023 2331 2311 3322 0200
编码解释:
332 301 第4 组字链链头(FB1) 003 段号 333 000 Ф 120 а202к222 т301ы 313 空格333 031–313 空格223 у213п220р310 я210м 120 а310 я313 空格122в131е 300 щ 302ь323.312 (控制符0D) 311 (控制符0A)332 202 链尾 00 文件补码
全文共23 个字符,21 个属于基本班组,2个属于辅助1 班组。班组代号333,班组内编码000,字母Ф;班组代号333,班组内编码031,符号“–”。算上段号,链体有26 个“半组元”,即13 个组元,不需要链内补码。再考虑链头、链尾,字链长15 个组元,是奇数,故最后有文件补码二进制4 位。
郭码文件长度也是23 个字节,纯属巧合,第三类字链的字符平均码长是二进制的8 位。
例12 网上下载的一段文章
俄国标准“西里尔文windows”单字节编码,全文共6809 个字节(略)。
第三类第4 组字链编码5225 个字节(略)。
全文有字符6809 个,其中151 个是辅助班组的,链体中段号及字符编码共有6961 个“半组元”,为奇数,链内补码。链体共有6962 个“半组元”,即3481 个组元。再加上链头、链尾2 个组元,全链共有3483 个组元,为奇数,文件补码二进制4 位,故文件长5225 个字节。
本例中,基本班组字符的使用频度为97.78%,辅助班组字符使用频度为2.22%。郭码第三类字链编码的字符平均码长6.1389 位,比ANSI 码(西里尔文windows)提高编码效率30.32%。
中国汉字和英文字符的使用频度数据比较权威,俄文字符使用频度是笔者自己统计的,由于统计对象数量不够多,频度数据误差可能大一些。
例13 由俄文、希腊文、汉文、日文、英文5种文字构成的短文
国际标准(Unicode)编码“FE FF 04 24 04 30 04 3A 04 42…… 00 20 00 6D 00 65 00 6E 00 2E ”,196 个字节。最前面的两个字节是Unicode 码的标识符,其后面是各个字符的码值,每个字符码长都是2 个字节。
中国标准(GB18030—2000)编码(略),154个字节,其中英文字符码长是1 个字节,其他文字字符码长都是2 个字节。
郭码编码“FB 10 FF 01 88 AA C7 7F CD DE B9 E8 D2 46 34 DD A7 70 CB BF A2 FB 11 1C 6A FD DC 82 38 37 9B 76 E0 6D 8A 61 62 29 A9 EF EF A2 D1 76 80 EA E9 CB C4 1F A3 11 31 42 12 51 15 0F A1 0D 11 51 09 11 E1 1D 12 51 20 0F A1 1D 10 D1 3D 0F CF A2 FA D7 28 87 2F 71 02 EB 65 03 1B 21 AE B0 31 CA 5B C0 9A EC 00 84 0B 25 B7 8F A2”,105 个字节。
编码解释(4 进制数):
俄文和希腊文使用第三类字链编码,它们同在第4 组字链,俄文在第3 段,希腊文在第4 段。中国汉字使用缺省方式编码。日文使用第一类字链编码。英文使用第二类符链编码。
写作本文使用的文字处理软件执行国家标准GB18030—2000,由于该标准中包括了俄文字符、希腊文字符和日文假名(都是2 字节编码),所以它可以对本例编码。如果俄文、希腊文、日文都使用本国标准编码(同属ANSI 码体系),它们是不可以同时使用的,也就不可以出现在同一个纯文本文件(txt)中。例如,俄国标准字母“щ”的码值是F9,希腊国家标准字母“ω”的码值也是F9。
由于研究方法的不断改进,就出现了后者超越前者的情况,对英文字符的编码第一类符链就没有第二类符链效率高,前者一般情况下就不太使用了。第一类符链奠定了链式编码的基本框架,很重要。
对小字符集文字的编码,第三类字链比第二类字链编码效率高。小字符集包括了几十种文字,许多种文字的使用规律和特点还不很清楚,还可能有难以预料的情况,故第二类字链的有关数据暂时还要保留。
郭码的数据结构决定了它有巨大的空间,开发了7 种编码方法之后,还有组元值4019 至4050 没有使用。如果它们全部用作区号,区位码的空间就有128000 个,这些都是可资利用的资源。
仅举一例,如果设4050 区为“短语编码”专区,就可以为4000 个短语编码。例如,设短语“中华人民共和国”的区位码是“4050 1”,短语“Universal Multiple-Octet Coded Character Set”的区位码是“4050 201”,等等。
如此一来,用一个2 组元的区位码就可以传递一个短语的全部信息,编码效率得到大幅度的提升。
空置空间为开发更多新功能提供了可能,具体能够拓展出什么新功能,那要由想象力来决定。
ANSI 码和Unicode 码已经使用了几十年,只要以字节为编码单位的模式不改变,提高文字编码效率的研究就没有出路。郭码根据国际上文字使用情况创建了新的编码单位——“组元”和“半组元”,由于操作空间变宽阔了,使得“缺省原理”和“变长码原理”得到了广泛应用,为提高文字编码效率奠定了基础。
ANSI 码和Unicode 码将一个个字符看作互不相关的个体,它们是对“个体”编码,一篇文章的编码仅仅是各个字符码值的简单排列。笔者研究了文字使用规律,发现同一种文字的字符之间有密切关系,就推出了多种链式编码,郭码将同一种文字的字符做“集体”编码,从而发挥了规模效应。
ANSI 码和Unicode 码中,一个字符的码值是唯一的、固定不变的。郭码中,一些字符在不同的编码方式中有不同的码值,它在文章中某处出现时应该采用哪种方式编码,需要由文字处理软件根据上下文的情况来决定,这就需要此个与郭码配套的文字处理软件应具有一定的“智能”。
郭码的基本方式编码码长为2 个组元(3 个字节),相比ANSI 码是“低效”的,这是小概率事件;缺省方式和链式编码能比ANSI 码“高效”,是大概率事件,所以总体上郭码比ANSI 码编码效率高。
理论上,郭码丰富了信息论中信源编码的方法和理念。
几十年来,科学技术发展迅速,信息的存储成本越来越低,计算机与通信网的速度越来越快,郭码编码效率高带来的经济效益渐渐被淡化,对个人来讲,这个效益是微不足道的,但对全球几十亿的用户而言,这个经济效益的总量还是相当可观的。