有學過一點程式的人應該對邏輯運算 AND, OR, NOT 都不陌生,許多程式還有支援 XOR。其中 AND, OR, XOR 可視為從 {0,1}2={(0,0),(0,1),(1,0),(1,1)} 打到 {0,1} 的函數。比如 AND 的定義就是 AND(0,0)=0, AND(0,1)=0, AND(1,0)=0, AND(1,1)=1。
其中 A,B 是輸入,分別都可為 0 或 1,而 C=AND(A,B) 是輸出。下面我們稱這種輸入兩個值得出一個值的邏輯閘為「二進一出」。如果是 NOT,那就只有「一進一出」。除了上面提到的幾個邏輯閘,另外還有三個常用的二進一出邏輯閘:NAND, NOR, XNOR,它們分別為 AND, OR 與 XOR 的「否定」,等同於做完 AND, OR, XOR 後再做 NOT。請注意,我們用一個正方形(或長方形)裡面寫 AND, OR, XOR… 表示要執行哪個運算,這只是方便。其實這些常用的邏輯閘都有自己的慣用圖示,網路上很容易搜尋到,這裡就不貼出來了。
我們可以用許多邏輯閘組成「邏輯電路」,比如下面是一個「純粹使用 XOR」所組成的邏輯電路:
所謂用邏輯閘「組成」電路,這個「組成」的規則為何我想無需過度描述,看圖例就很容易理解。但有兩件默認可以做的事,在許多資料中常常沒有講明(我指的是理想情形,現實中想必會有更多限制),一個是可以在某些地方直接加入 0 或 1 參與運算,另外一個就是可以進行「複製」,比如上圖中一開始 A 就先複製成兩份,其中一個走下面那條路與 B 進行了 XOR 之後,所得出來的值又複製成三份往後走。
像上面這樣,我們可以用邏輯閘組成各式各樣的邏輯電路,一般來說當然也不用侷限於「只用一種邏輯閘」這樣的規則。另外,雖然上圖的例子總地來看仍然是二進一出:輸入 A,B,輸出 f(A,B),不過顯然我們也可以隨意地構造出「m 進 n 出」的電路。有一個定理是說:我們可以用開頭所提到的那些常用邏輯閘來實現任意從 {0,1}m 打到 {0,1}n 的函數。這證明雖然不深奧,但也不是三兩句話可以解決,這裡我們就不去管它。
接著要解釋「通用邏輯閘」。一個邏輯閘被稱為通用邏輯閘,意思是只要使用這種邏輯閘就可以實現所有其他的邏輯閘(也因此只要用它就能實現所有從 {0,1}m 打到 {0,1}n 的函數)。何謂「實現其他的邏輯閘」?比如上面圖示的那個 f(A,B),如果它代入 (A,B)=(0,0),(0,1),(1,0),(1,1) 所得到的輸出值都與 AND 一樣,那我們就成功地「只用 XOR 實現 AND」了。(這可能嗎?你可以自己代代看,不過很快我們就會回答這個問題。)又比如不難看出 XOR(1,A)=NOT(A),或者 NAND(A,A)=NOT(A),所以 XOR 與 NAND 都可以用來實現 NOT。
所以,有誰是通用邏輯閘嗎?當然我們可以先排除 NOT,這傢伙是一進一出,變不出什麼花樣。所以重點在於那些常用的二進一出邏輯閘,有沒有人是通用邏輯閘。確實是有的,一個"眾所周知"的事實是:
NAND 與 NOR 是通用邏輯閘,而 XOR, AND, OR, XNOR 都不是。
要證明 NAND 與 NOR 是通用邏輯閘很單純,只要直接展示給你看它們怎麼生出其他的邏輯閘就行了。這可以參考 Wikipedia 的 Logic gate 裡面的 Universal logic gates 的部分。當然那些構造方式都是非常聰明的,要從無到有想出來並不容易,但一旦造出來了就很容易明白。像這樣,你問一件事可不可能,我直接做出來給你看,那就是可能了,這種構造性證明很容易理解。相對來說,很少看到有人清楚地解釋為什麼 XOR, AND, OR, XNOR 不是通用邏輯閘。以 XOR 為例,為什麼它不通用?這表示至少存在一種邏輯閘無法用 XOR 構造出來。這種「某事情不可能」的證明,通常就比較不直覺。因為你做不到,未必是不可能,也許只是努力還不夠。而且用邏輯閘構造邏輯電路的方式有無限多種,所以也無法使用窮舉法。必須想出某種「道理」,從根本上來否定我們要問的事情的可能性才行。一個常用的手法就是想辦法證明「所有使用這種邏輯閘構造出來的邏輯電路都一定滿足某種性質」,而這個「性質」就自然地給出了一個限制。對於 XOR 不是通用邏輯閘這件事,我第一次聽到的時候就聽說是要觀察「0 與 1 的數量的奇偶性」這件事,但這具體到底是什麼意思我一直搞不清楚,直到看到這個討論才終於明白。主要就是因為 XOR 有下述性質:
若 a1,a2,a3,a4 四個數中有偶數個 0,偶數個 1,且 b1,b2,b3,b4 亦然,則 XOR(a1,b1),XOR(a2,b2),XOR(a3,b3),XOR(a4,b4) 中同樣有偶數個 0,偶數個 1。
這個性質可以直接檢查,這裡就不詳細討論(是否有什麼比較聰明的檢查方式我也沒細想,反正最慘就是把所有可能的情形都列出來)。從這個性質出發,我們即可推論出:「任何一個純粹由 XOR 所組成的二進一出邏輯電路 f(A,B),都會滿足 f(0,0), f(0,1), f(1,0), f(1,1) 四個數中有偶數個 0,偶數個 1。」事實上,在這樣的電路中的「任何一處」,都會滿足下述的性質:
把 (A,B)=(0,0),(0,1),(1,0),(1,1) 四種輸入在該處所對應的數值記作 x1,x2,x3,x4,則 x1∼x4 這四個數中有偶數個 0,偶數個 1。
為什麼會這樣?我們不做太形式化的證明,用「觀察」應該就可以充分地說服自己。首先讓我們把上述性質稱為「(在該處)保持偶數」,然後我們再重貼一次前面那個電路圖:
現在讓我們來好好觀察一下。一開始上面的 1 與 A 通過 XOR 之後的值,是否「保持偶數」?是的,因為對應 (A,B)=(0,0),(0,1),(1,0),(1,1),得到的值為 XOR(1,0)=1, XOR(1,0)=1, XOR(1,1)=0, XOR(1,1)=0(請注意上面對「保持偶數」的描述!雖然這一步只有 1 與 A 交互作用,但還是要把 (A,B) 的所有可能都一起看)。類似這樣,接著再觀察,下面 A 與 B 經過 XOR 產生的值,是否也「保持偶數」?然後,如果在電路的某處有「保持偶數」,往後走,遇到另一個「保持偶數」的地方來的值,進行 XOR,是否仍然「保持偶數」?思考一下,會發現這些問題的答案都是「是」。這樣一路到最後,輸出的 f(A,B) 自然也「保持偶數」。這就限制了 f(A,B) 的可能性,比如說,它就不可能是 AND。使用上面這個聰明的論證方式,我們也可以證明 XNOR 不是通用邏輯閘,但對於 AND 與 OR 就行不通了,因為它們並沒有「保持偶數」的特性。那為什麼它們不通用呢?NAND 與 NOR 不過就是它們的相反,卻是通用的,乍看之下這真的有點奇妙。事實上,AND 與 OR 不是通用邏輯閘,都有更簡單(知道了就很簡單,不知道時根本想不到)的看法。對於單純使用 AND 構造的二進一出電路,只要注意到下面這件事即可:無論構造的電路如何複雜,輸入值 A,B 中只要有一個是 0,最終輸出結果必為 0。而對於單純使用 OR 構造的電路則正相反:輸入值只要有一個人是 1,最終結果必為 1。這樣的特性顯然使得 AND 與 OR 不可能是通用邏輯閘。這樣,我們就把全部的問題都解決了。
沒有留言:
張貼留言