Unicode和Python的中文處理


Unicode和Python的中文處理

http://blog.csdn.net/tingsking18/archive/2009/03/29/4033645.aspx

  在Python語言中,Uincode字符串處理一直是一個容易讓人迷惑的問題。許多Python愛好者經常因為搞不清Unicode、UTF-8還有其它許許多多的編碼之間的區別而大傷腦筋。筆者曾經也是這“傷腦筋一族”的成員,但經過半年多的努力,現在終於初步弄清楚其中的一些關系。現將其整理如下,與各位同仁同享。同時也希望能借這篇短文拋磚引玉,吸引更多真正的高手加入進來,共同完善我們的Python中文環境。

  本文所提到的各種觀點,一部分是查閱資料所得,還有一部分是筆者利用已有各種編碼數據用“猜測加驗證”法得到。筆者自問才疏學淺,其中怕是藏有不少錯誤。各位看官中不乏高手,如果有哪一位發現其中哪里有錯,萬望各位高人不吝賜教。筆者自己丟丑事小,觀點錯誤誤了別人事大,因此各位大可不必顧忌筆者的面子問題。


第一節 文字編碼和Unicode標准

  要解釋Unicode字符串就必須先從什么是Unicode編碼開始說起。眾所周知,文本顯示一直是計算機顯示功能必須解決的基本問題。而計算機並不識字,它實際上是把文本看做是一串“圖片”,每張“圖片”對應一個字符。每個計算機程序在顯示文本時,必須借助一個記錄這個文字“圖片”如何顯示的“圖片”集合,從中找到每一個字符對應“圖片”的數據,並依樣畫葫蘆地把這個字“畫”到屏幕上。這個“圖片”就被稱為“字模”,而記錄字模顯示數據的集合就被稱為“字符集”。為方便程序查找,每個字符的字模數據在字符集中必須是有序排列的,而且每個字符都會被分配一個獨一無二的ID,這個ID就是字符的編碼。而在計算機進行字符數據處理時,總是用這個編碼代表它表示的那個字符。因此,一個字符集就規定了一組計算機能夠處理的字符數據。顯然,不同國家指定的字符集大小不同,相應的字符編碼也不同。

  在計算機歷史上,最為廣泛使用的標准化字符集當首推ASCII字符集。它實際上是美國制訂的標准,針對北美用戶開發。它使用7個二進制位編碼,可以表示128個字符。這個字符集最終被ISO組織正式采納為國際標准,並且大量應用在各種計算機體系上。現如今,所有PC機的BIOS中都內含了ASCII字符集的字模,其深入人心可見一斑。

  但是,當計算機在各個國家大規模普及時,ASCII編碼的局限性就暴露出來了:它的字符空間實在有限,無法容納更多的字符,可是絕大多數語言需要使用的字符數目都遠不止128個。為了能正確處理本國文字,各個國家官方或民間紛紛開始了設計本國文字編碼集的工作,並且最終涌現出許許多多針對各個國家文字的字符編碼,如針對西歐字符的ISO-8859-1編碼,針對簡體中文的GB系列編碼,還有針對日文的SHIFT-JIS編碼等等。同時,為了保證各個新的字符集能夠兼容原本的ASCII文本,大多數字符集不約而同地都將ASCII字符作為自己前128個字符,並使其編碼與ASCII編碼一一對應。

  這樣一來,各國文字的顯示問題是解決了,可是又帶來一個新的問題:亂碼。不同國家、地區使用的字符集通常沒有統一的規范進行約束,因此各個字符集編碼往往互不兼容。同一個字在兩個不同的字符集中編碼一般不同;而同一個編碼在不同的字符集中對應的字符也不一樣。一段用編碼A編寫的文本在一個只支持編碼B的系統上往往會被顯示成一堆亂七八糟的字符。更糟糕的是,不同字符集使用的編碼長度往往也不相同,那些只能處理單字節編碼的程序在遇到雙字節甚至是多字節編碼的文本時,往往因為不能正確處理而產生了臭名昭著的“半個字”問題。這使得本已經混亂不堪的局面更是亂成了一團粥。

  為了一勞永逸地解決這些問題,業界許多大公司和組織聯合提出了一個標准,這就是Unicode。Unicode實際上是一種新的字符編碼體系。它對字符集中的每個字符用兩個字節長的ID號進行編碼,從而規定出一個可容納多達65536個字符的編碼空間,並且將現今國際上各國編碼中的常用字盡數收入罄中。由於在設計編碼時有了周全的考慮,Unicode很好地解決了其它字符集在進行數據交流時的亂碼和“半個字”問題。同時,Unicode的設計者充分考慮到現今大量字模數據使用的仍是各國制訂的各種編碼這一現實,提出了“將Unicode作為內部編碼”的設計理念。也就是說,字符顯示程序依然使用原先的編碼和代碼,而應用程序的內部邏輯使用的將是Unicode。當要進行文字顯示時,程序總是將Unicode編碼的字符串轉換成原本的編碼進行顯示。這樣,大家就不必為了使用Unicode而重新設計字模數據體系了。同時,為了與各國已經制訂的編碼相區別,Unicode的設計者將Unicode稱為“寬字符編碼”(wide characters encodings),而各國制訂的編碼習慣上被稱為“多字節編碼”(multi bypes encodings)。時至今日,Unicode體系又引入了四字節的擴展編碼,並且逐漸與與UCS-4,也就是ISO10646編碼規范合流,希望有朝一日能夠用ISO10646體系統一全世界所有的文字編碼。

  Unicode體系甫一出世便被大家寄予厚望,並被迅速接受為ISO認可的國際標准。但是,Unicode在推廣過程中卻遭到了首先是歐美用戶的反對。他們反對的理由非常簡單:歐美用戶原本使用的編碼都是單字節長的,雙字節的Unicode處理引擎無法處理原本的單字節數據;而如果要把現有的單字節文本全部轉換成Unicode,工作量就太大了。再說,如果所有的單字節編碼文本都被轉換成雙字節的Unicode編碼,他們所有的文本數據占用的空間都會變成原來的兩倍,而且所有的處理程序都要被重新編寫。這個開銷他們無法接受。

  雖然Unicode是國際認可的標准,但是標准化組織不可能不考慮歐美用戶這個最大的計算機使用群體的要求。於是在各方磋商之下,一個Unicode的變種版本產生了,這就是UTF-8。UTF-8是一個多字節的編碼體系,它的編碼規則如下:

  1、UTF-8編碼分為四個區:
    一區為單字節編碼,
      編碼格式為:0xxxxxxx;
      對應Unicode:0x0000 - 0x007f
    二區為雙字節編碼,
      編碼格式為:110xxxxx 10xxxxxx;
      對應Unicode:0x0080 - 0x07ff
    三區為三字節編碼,
      編碼格式為:1110xxxx 10xxxxxxx 10xxxxxx
      對應Unicode:0x0800 - 0xffff
    四區為四字節編碼,
      編碼格式為:11110xxx 10xxxxxxx 10xxxxxx 10xxxxxx
      對應Unicode:0x00010000 - 0x0001ffff
    五區為五字節編碼,
      編碼格式為:111110xx 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx
      對應Unicode:0x00200000 - 0x03ffffff
    六區為六字節編碼,
      編碼格式為:111110x 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx 10xxxxxxx
      對應Unicode:0x04000000 - 0x7fffffff

   其中,一、二、三區對應Unicode的雙字節編碼區,而四區則針對Unicode的四字節擴展部分(按照該定義,UTF-8還有五區和六區,但筆者並未在GNU glibc庫中發現,不知為何);

  2、各個區按照一、二、三、四、五、六順序排列,其對應位置上的字符與Unicode保持相同;

  3、不可顯示的Unicode字符編碼為0字節,換言之,它們沒有被收入UTF-8(這是筆者從GNU C庫注釋中得到的說法,可能與實際情況不符);

  按照UTF-8編碼規則我們不難發現,其一區的128個編碼實際上就是ASCII編碼。所以UTF-8的處理引擎可以直接處理ASCII文本。但是,UTF-8對ASCII編碼的兼容是以犧牲其它編碼為代價的。比如,原本中、日、韓三國文字基本上都是雙字節編碼,但它們在Unicode編碼中的位置對應到UTF-8中的三區,每一個字符編碼要三個字節長。換句話說,如果我們把所有現有的中、日、韓三國編碼的非ASCII字符文本數據轉換成UTF-8編碼,則其大小都會變成原來的1.5倍。

  雖然筆者個人認為UTF-8的編碼方式顯得有些不夠公平,但它畢竟解決了ASCII文本到Unicode世界的過渡問題,所以還是贏得了廣泛的認可。典型的例子是XML和Java:XML文本的默認編碼就是UTF-8,而Java源代碼實際上就可以用UTF-8字符編寫(JBuilder的用戶應該有印象)。另外還有開源軟件世界中大名鼎鼎的GTK 2.0,它使用UTF-8字符作為內部編碼。

  說了這么多,似乎話題有些扯遠了,許多Python愛好者可能已經開始着急:“這和Python有什么關系呢?”好的,現在我們就把視線轉到Python的世界來。


第二節 Python的Unicode編碼系統

  為了正確處理多語言文本,Python在2.0版后引入了Unicode字符串。從那時起,Python語言中的字符串就分為兩種:一種是2.0版之前就已經使用很久的傳統Python字符串,一種則是新的Unicode字符串。在Python語言中,我們使用unicode()內建函數對一個傳統Python字符串進行“解碼”,得到一個Unicode字符串,然后又通過Unicode字符串的encode()方法對這個Unicode字符串進行“編碼”,將其“編碼”成為傳統Python字符串以上內容想必每一個Python用戶都是爛熟於胸了。但是你可知道,Python的Unicode字符串並不是真正意義上的“Unicode編碼的字符串”,而是遵循一種自己特有的規則。這個規則的內容簡單得很:

  1、ASCII字符的Python Unicode編碼與它們的ASCII編碼相同。也就是說,Python的Unicode字符串中ASCII文本仍然是單字節長度編碼;

  2、ASCII字符以外的字符,其編碼就是Unicode標准編碼的雙字節(或四字節)編碼。
    (筆者猜想,之所以Python社群要制訂如此古怪的標准,可能是想保證ASCII字符串的通用性吧)

  通常在Python應用中,Unicode字符串都是作為內部處理時使用,而終端顯示工作則由傳統的Python字符串完成(實際上,Python的print語句根本無法打印出雙字節的Unicode編碼字符)。在Python語言中,傳統Python字符串就是所謂的“多字節編碼”字符串,用於表示各種被“編碼”成為具體字符集編碼的字符串(比如GB、BIG5、KOI8-R、JIS、ISO-8859-1,當然也有UTF-8);而Python Unicode字符串則是“寬字符編碼”字符串,表示從具體字符集編碼中“解碼”出來的Unicode數據。所以通常情況下,一個需要用到Unicode編碼的Python應用往往會以如下方式處理字符串數據:

def foo(string, encoding = "gb2312"):
# 1. convert multi-byte string to wide character string
u_string = unicode(string, encoding)

# 2. do something
...

# 3. convert wide character string to printable multi-byte string
return u_string.encode(encoding)

 

  我們可以舉出一個例子:經常在Red Hat Linux環境中使用PyGTK2進行XWindow編程的Python同道可能早就發現過這樣的情況:如果我們直接寫出如下語句:

import pygtk
pygtk.require('2.0')
import gtk

main = gtk.Window() # create a window
main.set_title("你好") # NOTICE!

 

  這樣的語句在執行時會在終端上出現這樣的警告:
  Error converting from UTF-8 to 'GB18030': 轉換輸入中出現無效字符序列並且程序窗口標題不會被置為“你好”;

  但如果用戶安裝了中文的codec,並將上文的最后一句改為:

u_string = unicode('你好','gb2312')
main.set_title(u_string)

則程序窗口標題將會被正確地設置為“你好”。這是為什么呢?

  原因很簡單。gtk.Window.set_title()方法總是將自己接收的標題字符串看做是一個Unicode字符串。PyGTK系統在接收到用戶的main.set_title()這一請求時,將得到的字符串在某處做了如下處理:

class Window(gtk.Widget):
...
def set_title(self, title_unicode_string):
...
# NOTICE! unicode -> multi-byte utf-8
real_title_string = title_unicode_string.encode('utf-8')
...
# pass read_title_string to GTK2 C API to draw the title
...

 


  我們看到,字符串title_unicode_string在程序內部被“編碼”成了一個新的字符串:real_title_string。顯然,這個real_title_string是一個傳統Python字符串,而它的編碼用的是UTF-8。在上一節中筆者曾經提到過,GTK2的內部使用的字符串都是按UTF-8編碼的,所以,GTK2核心系統在接收到real_title_string后可以正確顯示出標題來。

  那么,如果用戶輸入的標題是ASCII字符串(比如:“hello world”),又當如何?我們回想一下Python Unicode字符串的定義規則就不難發現,如果用戶的輸入是ASCII字符串,則對其進行重編碼得到的就是其自身。也就是說,如果title_unicode_string的值是ASCII字符串,則real_title_string與title_unicode_string的值將完全一致。而一個ASCII字符串也就是一個UTF-8字符串,把它傳遞給GTK2系統不會有任何問題。

  以上我們舉的例子是關於Linux下的PyGTK2的,但類似的問題不僅出現在PyGTK中。除了PyGTK之外,現今各種Python綁定的圖形包,如PyQT、Tkinter等,多多少少都會遇到與Unicode處理有關的問題。

  現在我們弄清了Python的Unicode字符串編碼機制,但是我們最想知道的問題還是沒有解決:我們如何才能讓Python支持用Unicode處理中文呢?這個問題我們將在下一節說明。


第三節 如何讓Python的Unicode字符串支持中文

  看完這一節的標題,有一些Python同道們可能會有些不以為然:“為什么一定要用Unicode處理中文呢?我們平時用傳統Python字符串處理得不是也不錯嗎?”的確,其實在一般情況下像字符串連接、子串匹配等操作用傳統Python字符串也就足夠了。但是,如果涉及到一些高級的字符串操作,比如包含多國文字的正則表達式匹配、文本編輯、表達式分析等等,這些大量混雜了單字節和多字節文本的操作如果用傳統字符串處理就非常麻煩了。再說,傳統字符串始終無法解決那該死的“半個字”問題。而如果我們可以使用Unicode,則這些問題都可以迎刃而解。所以,我們必須正視並設法解決中文Unicode的處理問題。

  由上一節的介紹我們知道,如果要想利用Python的Unicode機制處理字符串,只要能夠擁有一個能夠把多字節的中文編碼(包括GB編碼系列和BIG5系列)和Unicode編碼進行雙向轉換的編碼/解碼模塊就可以了。按照Python的術語,這樣的編碼/解碼模塊被稱為codec。於是接下來的問題就變成了:我們該如何編寫這樣一個codec?

  如果Python的Unicode機制是硬編碼在Python核心中的話,那么給Python添加一個新的codec就將是一項艱苦卓絕的工作了。幸虧Python的設計者們沒有那么傻,他們提供了一個擴充性極佳的機制,可以非常方便地為Python添加新的codecs。

  Python的Unicode處理模塊有三個最重要的組成部分:一是codecs.py文件,二是encodings目錄,三是aliases.py文件。前兩者都位於Python系統庫的安裝目錄之中(如果是Win32發行版,就在$PYTHON_HOME/lib/目錄下;如果是Red Hat Linux,就在/usr/lib/python-version/目錄下,其它系統可以照此尋找),而最后一個則位於encodings目錄下。接下來,我們分別對這三者加以說明。

  先來看看codecs.py文件。這個文件定義了一個標准的Codec模塊應有的接口。其具體內容大家可以在自己的Python發行版中找到,在此不再贅述。按照codecs.py文件的定義,一個完整的codec應該至少擁有三個類和一個標准函數:

  1、Codec類

  用途:
    用於將用戶傳入的緩沖區數據(一個buffer)作為一個傳統Python字符串,並將其“解碼”為對應的Unicode字符串。一個完整的Codec類定義必須提供Codec.decode()和Codec.encode()兩個方法:

Codec.decode(input, errors = "strict")


  用於將輸入的數據看做是傳統Python字符串,並將其“解碼”,轉換成對應的Unicode字符串。

  參數:

  input:       輸入的buffer(可以是字符串,也可以是任何可以轉換成字符串表示的對象)
  errors:      發生轉換錯誤時的處理選擇。可選擇如下三種取值:
  strict(默認值):  如果發生錯誤,則拋出UnicodeError異常;
  replace:      如果發生錯誤,則選取一個默認的Unicode編碼代替之;
  ignore:      如果發生錯誤,則忽略這個字符,並繼續分析余下的字符。

  返回值:
    一個常數列表(tuple):首元素為轉換后的Unicode字符串,尾元素為輸入數據的長度。

Codec.encode(input, errors = "strict")


  用於將輸入的數據看做是Unicode字符串,並將其“編碼”,轉換成對應的傳統Python字符串。

  參數:

  input:輸入的buffer(通常就是Unicode字符串)
  errors:發生轉換錯誤時的處理選擇。取值規則與Codec.decode()方法相同。

  返回值:
    一個常數列表(tuple):首元素為轉換后的傳統Python字符串,尾元素為輸入數據的長度。

  2、StreamReader類(通常應該繼承自Codec類)

  用於分析文件輸入流。提供所有對文件對象的讀取操作,如readline()方法等。

  3、StreamWriter類(通常應該繼承自Codec類)

  用於分析文件輸出流。提供所有對文件對象的寫入操作,如writeline()方法等。

  5、getregentry()函數

  即“GET REGistry ENTRY”之意,用於獲取各個Codec文件中定義的四個關鍵函數。其函數體統一為:

def getregentry():
return tuple(Codec().encode,Codec().decode,StreamReader,StreamWriter)


  在以上提到的所有四個類中,實際上只有Codec類和getregentry()函數是必須提供的。必須提供前者是因為它是實際提供轉換操作的模塊;而后者則是Python系統獲得Codec定義的標准接口,所以必須存在。至於StreamReader和StreamWriter,理論上應該可以通過繼承codecs.py中的StreamReader和StreamWriter類,並使用它們的默認實現。當然,也有許多codec中將這兩個類進行了改寫,以實現一些特殊的定制功能。


  接下來我們再說說encodings目錄。顧名思義,encodings目錄就是Python系統默認的存放所有已經安裝的codec的地方。我們可以在這里找到所有Python發行版自帶的codecs。習慣上,每一個新的codec都會將自己安裝在這里。需要注意的是,Python系統其實並不要求所有的codec都必須安裝於此。用戶可以將新的codec放在任何自己喜歡的位置,只要Python系統的搜索路徑可以找得到就行。


  僅僅將自己寫的codec安裝在Python能夠找到的路徑中還不夠。要想讓Python系統能找到對應的codec,還必須在Python中對其進行注冊。要想注冊一個新的codec,就必須用到encodings目錄下的aliases.py文件。這個文件中只定義了一個哈希表aliases,它的每個鍵對應着每一個codec在使用時的名稱,也就是unicode()內建函數的第二個參數值;而每個鍵對應的值則是一個字符串,它是這個codec對應的那個處理文件的模塊名。比如,Python默認的解析UTF-8的codec是utf_8.py,它存放在encodings子目錄下,則aliases哈希表中就有一項表示其對應關系:

'utf-8' : 'utf_8', # the module `utf_8' is the codec for UTF-8

 

同理,如果我們新寫了一個解析‘mycharset’字符集的codec,假設其編碼文件為mycodec.py,存放在$PYTHON_HOME/lib/site-packages/mycharset/目錄下,則我們就必須在aliases哈希表中加入這么一行:

'mycharset' : 'mycharset.mycodec',


這里不必寫出mycodec.py的全路徑名,因為site-packages目錄通常都在Python系統的搜索路徑之中。

  Python解釋器在需要分析Unicode字符串時,會自動加載encodings目錄下的這個aliases.py文件。如果mycharset已經在系統中注冊過,則我們就可以像使用其它內建的編碼那樣使用我們自己定義的codec了。比如,如果按照上面的方式注冊了mycodec.py,則我們就可以這樣寫:

my_unicode_string = unicode(a_multi_byte_string, 'mycharset')
print my_unicode_string.encode('mycharset')


  現在我們可以總結一下要編寫一個新的codec一共需要那些步驟:

  首先,我們需要編寫一個自己的codec編碼/解碼模塊;

  其次,我們要把這個模塊文件放在一個Python解釋器可以找到的地方;

  最后,我們要在encodings/aliases.py文件中對其進行注冊。


  從理論上說,有了這三步,我們就可以將自己的codec安裝到系統中去了。不過這樣還不算完,還有一個小問題。有時候,我們出於種種原因,不希望隨便修改自己的系統文件(比如,一個用戶工作在一個集中式的系統中,系統管理員不允許別人對系統文件進行修改)。在以上介紹的步驟中,我們需要修改aliases.py文件的內容,這是一個系統文件。可如果我們不能修改它,難道我們就不能添加新的codec嗎?不,我們當然有辦法。

  這個辦法就是:在運行時修改encodings.aliases.aliases哈希表的內容。

  還是使用上面那個假設,如果用戶工作系統的管理員不允許用戶把mycodec.py的注冊信息寫入aliases.py,那么我們就可以如此處理:

  1、將mycodec.py放在一個目錄下,比如/home/myname/mycharset/目錄;

  2、這樣編寫/home/myname/mycharset/__init__.py文件:

import encodings.aliases

# update aliases hash map
encodings.aliases.aliases.update({\
'mycodec' : 'mycharset.mycodec',\
}}

  以后每次要使用Python時,我們可以將/home/myname/加入搜索路徑,並且在使用自己的codec時預先執行:

import mycharset # execute the script in mycharset/__init__.py

 

  這樣我們就可以在不改動原有系統文件的情況下使用新的codecs了。另外,如果借助Python的site機制,我們還可以讓這個import工作自動化。如果大家不知道什么是site,就請在自己的Python交互環境中運行:

import site
print site.__doc__


瀏覽一下site模塊的文檔,即可明白個中技巧。如果大家手頭有Red Hat Linux v8,v9,還可以參考一下Red Hat的Python發行版中附帶的日文codec,看看它是如何實現自動加載的。也許不少同道可能找不到這個日文的codec在哪里,這里列出如下:

Red Hat Linux v8:在/usr/lib/python2.2/site-package/japanese/目錄下;
  Red Hat Linux v9:在/usr/lib/python2.2/lib-dynload/japanese/目錄下;

 

提示:請Red Hat用戶注意site-packages目錄下的japanese.pth文件,結合site模塊的文檔,相信馬上就能豁然開朗。


結束語

  記得當初筆者在Dohao論壇上誇下海口:“如果可以的話,我可以為大家編寫一個(中文模塊)”,現在回想起來,不禁為自己當初的不知天高地厚而汗顏。一個把自己所有的的時間都花在學習上,一個學期只學七門課程,還落得個兩門課不及格的傻瓜研究生,哪里有什么資格在大家面前如此囂張。現如今,第二個學期由於這兩門課的緣故負擔陡增(十門課呀!),家中老父老母還眼巴巴地等着自己的兒子能給他們掙臉。要想在有限的時間之內,既保證學習,又保證工作(我要承擔導師的課程輔導工作,同時還有一個學校的教學改革方案需要我在其中挑大梁),已經是疲於應付,再加上一個中文模塊……唉,請恕筆者分身乏術,不得不食言。

  因此,筆者斗膽,在此和盤托出自己這半年以來的心得,只希望能夠找到一批,不,哪怕是一個也好,只要是對這個項目感興趣的同道中人,能夠接下筆者已經整理出來的知識,把一個完整的(至少應該包含GB、BIG5、筆者個人認為甚至還應包括HZ碼)中文模塊編寫出來,貢獻給大家(不論是有償的還是無償的),那就是我們廣大Python愛好者之福了。另外,Python的發行版至今尚未包括任何中文支持模塊。既然我等平日深愛Python,如果我們的工作能因此為Python的發展做出一點貢獻,何樂而不為呢?


附錄 幾個小小提示

  1、LUO Jian兄已經編寫了一個非常不錯的中文模塊(Dohao上有鏈接,文件名是showfile.zip,這個模塊比我已經寫完的草稿版本要快得多),同時支持GB2312和GB18030編碼,可惜不支持BIG5。如果大家有興趣,可以下載這個模塊研究一下;

  2、和其它字符集編碼相比,中文模塊有其特殊性,那就是其海量的字符數目。一些相對較小的字符集還好說,比如GB2312,可以利用哈希表查找。而對於巨大的GB18030編碼,如果簡單地將所有數據制成一個特大的編碼對照表,則查詢速度會慢得讓人無法容忍(筆者在編寫模塊時最頭疼的就是這一點)。如果要編寫一個速度上能讓人滿意的codec,就必須考慮設計某種公式,能夠通過簡單地運算從一種編碼推算出另一種來,或者至少能推算出它的大概范圍。這就要求程序員要能對整個編碼方案做統計,設法找到規律。筆者認為,這應該是編寫中文模塊時的最大難點。或許是數學功底實在太差的緣故,筆者費盡心機也未能找出一個規律來。希望能有數學高手不吝賜教;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM