本教材的使用方式:本講義整合了第一週四份投影片 (1.1 Boolean Algebra、1.2 Finding Formula、1.3 Logic Gates、1.4 NAND) 的全部內容,並補充了背景知識、詳細推導、歷史脈絡與延伸練習。 每章結尾附有「本章重點」整理;第 5 章為綜合練習題,附完整詳解。 建議先讀懂每個定義與例題,再自行完成練習題後對照解答。

二進位表示:一切從「兩種狀態」開始

每一種數位裝置都使用二進位(binary)資料表示法,也就是「兩種狀態」:

狀態 邏輯意義 物理意義
\(1\) TRUE(真) 「開(on)」,電流正在流動
\(0\) FALSE(假) 「關(off)」,電流沒有流動

電腦內部的一切——數字、文字、圖片、程式——最終都被編碼成這兩種狀態的序列。 若要研究這些訊號如何被操作與轉換,我們需要一套數學工具: 布林代數(Boolean algebra)

歷史小知識:布林代數得名於英國數學家 George Boole, 他在 1854 年的著作《The Laws of Thought》中將邏輯推理系統化為代數運算。 1938 年,Claude Shannon 在其碩士論文中證明布林代數可以完整描述 繼電器開關電路的行為,從此奠定了數位電路設計的理論基礎—— 這篇論文常被譽為「二十世紀最重要的碩士論文」。

命題(Propositions)

命題(proposition)是一個非真即假的敘述句。 判斷一個敘述是否為命題的好方法:在句子前面加上「it is true that…(以下敘述為真:)」, 若加上後語意通順、可以判斷真假,它就是命題。

例如,對一個三邊為 \(a\)\(b\)\(c\) 的三角形,下列都是命題:

命題 命題變數
\(a\) 與邊 \(b\) 等長 \(x\)
\(b\) 與邊 \(c\) 等長 \(y\)
\(c\) 與邊 \(a\) 等長 \(z\)

每個命題可以用一個命題變數(propositional variable)代替, 變數的值就是該命題的真假值。變數名稱可以任取,但依慣例(也為了簡潔)使用字母。

非命題的例子與其「命題化」的方式:

非命題 \(\Longrightarrow\) 修改成命題
「這是什麼三角形?」(疑問句) 「它是正三角形」
「邊 \(a\) + 邊 \(b\)」(只是個算式) 「邊 \(a\) + 邊 \(b\) = 邊 \(c\)

基本邏輯運算子(Logical Operators)

三個基本運算子(basic operators)足以組合出任何邏輯表達式:

\(\lnot A\) \(A \land B\) \(A \lor B\)
正式名稱 否定(Negation / Complement) 合取(Conjunction) 析取(Disjunction)
自然語言 not \(A\)(非 \(A\) \(A\) and \(B\)\(A\)\(B\) \(A\) or \(B\)\(A\)\(B\)
替代寫法 \(\bar{A}\) \(A \cdot B\) \(A + B\)
C 語言 !A A && B A || B

注意:\(A \lor B\)包含性的或(inclusive or)—— 「\(A\)\(B\) 或兩者皆真」時輸出為真。 這與日常語言中常見的「二選一」(排他性的或)不同,後者是 \(\oplus\)(XOR),稍後介紹。

真值表(Truth Tables)

真值表(truth table)列出一個邏輯公式所有可能的輸入組合 與其對應的輸出值。\(n\) 個輸入變數會產生 \(2^n\) 列。

三個基本運算子的真值表:

\(A\) \(B\) \(\lnot A\)
0 0 1
0 1 1
1 0 0
1 1 0
\(A\) \(B\) \(A \land B\)
0 0 0
0 1 0
1 0 0
1 1 1
\(A\) \(B\) \(A \lor B\)
0 0 0
0 1 1
1 0 1
1 1 1

記憶要點:\(\land\)(AND)「全部為 1 才是 1」;\(\lor\)(OR)「至少一個 1 就是 1」。

文氏圖(Venn Diagrams)

文氏圖用「面積」表達邏輯運算:矩形代表所有可能情況, 圓 \(A\) 內部代表「\(A\) 為真」的情況,塗色區域代表「公式輸出為真」的情況。

\(\lnot A\)\(A\) 為假的所有情況 \(A \land B\)\(A\)\(B\) 皆真 \(A \lor B\):至少一者為真
\(A \oplus B\):恰有一者為真 \(A \to B\):排除「\(A\)\(B\) 假」 \(A \leftrightarrow B\):真假值相同

組合運算子:三角形的例子

回到三角形的三個命題(\(x\)\(a=b\)\(y\)\(b=c\)\(z\)\(c=a\)), 我們可以用邏輯運算子把它們組合成複合命題(compound propositions)。 必要時用括號標明運算順序。

\(x\)\(y\)\(z\) 寫出下列判斷式:

  1. 正三角形(三邊皆等長)?

  2. 不等邊三角形(沒有任何兩邊等長)?

  3. 等腰三角形(恰好兩邊等長)?

  1. \(x \land y \land z\) —— 三個等長關係必須全部成立。

  2. \(\lnot x \land \lnot y \land \lnot z\) —— 三個等長關係必須全部不成立。

  3. \((x \lor y \lor z) \land \lnot(x \land y \land z)\) —— 「至少有一組邊等長」「不是三邊全等長」。 這裡有個微妙之處:對實際的三角形而言,若 \(x\)\(y\)\(z\) 中任兩個為真, 第三個必然為真(等長關係有遞移性),所以「至少一組等長且非全部等長」 就等價於「恰好一組等長」。

更多邏輯運算子

除了三個基本運算子外,還有三個常用運算子。 重要的是:它們都可以用基本運算子表達

\(A \oplus B\) \(A \to B\) \(A \leftrightarrow B\)
正式名稱 互斥析取(XOR) 蘊含(Implication) 等價(Equivalence)
自然語言 exclusively \(A\) or \(B\) \(A\) implies \(B\) \(A\) is equivalent to \(B\)
基本運算子表示 \((\lnot A \lor \lnot B) \land (A \lor B)\) \(\lnot A \lor B\) \((\lnot A \lor B) \land (\lnot B \lor A)\)

六個運算子的完整真值表:

\(A\) \(B\) \(\lnot A\) \(A \land B\) \(A \lor B\) \(A \oplus B\) \(A \to B\) \(A \leftrightarrow B\)
0 0 1 0 0 0 1 1
0 1 1 0 1 1 1 0
1 0 0 0 1 1 0 0
1 1 0 1 1 0 1 1

幾個幫助理解的觀察:

  • XOR(\(\oplus\):「恰好一個為真」。也可以想成「\(A \ne B\)」或 「不進位的二進位加法」。\(A \oplus B \equiv (A \lor B) \land \lnot(A \land B)\) 是另一個常見的等價寫法。

  • 蘊含(\(\to\)\(A \to B \equiv \lnot A \lor B\)。 唯一為假的情形是「\(A\) 真而 \(B\) 假」。 注意當 \(A\) 為假時整個式子必為真(前提不成立,承諾自動成立)。 用自然語言帶入命題有助於直覺:「如果下雨(\(A\)),那麼地會濕(\(B\))」—— 沒下雨時,不論地濕不濕,這句話都沒有被違反。

  • 等價(\(\leftrightarrow\)\(A \leftrightarrow B \equiv (A \to B) \land (B \to A)\), 即「互相蘊含」。輸出為真恰好在 \(A\)\(B\) 真假值相同時; 它正是 XOR 的否定:\(A \leftrightarrow B \equiv \lnot(A \oplus B)\)

完成複雜公式的真值表

要計算複雜布林表達式的真值表,只要把每個變數換成該列的輸入值,然後逐步化簡

逐列代入並化簡:

\(A\) \(B\) \(C\) 代入化簡過程 輸出
0 0 0 \(((0 \land 0) \lor \lnot 0) \equiv (0 \lor 1)\) \(1\)
0 0 1 \(((0 \land 0) \lor \lnot 1) \equiv (0 \lor 0)\) \(0\)
0 1 0 \(((0 \land 1) \lor \lnot 0) \equiv (0 \lor 1)\) \(1\)
0 1 1 \(((0 \land 1) \lor \lnot 1) \equiv (0 \lor 0)\) \(0\)
1 0 0 \(((1 \land 0) \lor \lnot 0) \equiv (0 \lor 1)\) \(1\)
1 0 1 \(((1 \land 0) \lor \lnot 1) \equiv (0 \lor 0)\) \(0\)
1 1 0 \(((1 \land 1) \lor \lnot 0) \equiv (1 \lor 1)\) \(1\)
1 1 1 \(((1 \land 1) \lor \lnot 1) \equiv (1 \lor 0)\) \(1\)

邏輯等價(Logical Equivalence)

每個邏輯公式恰有一張真值表與之對應; 但每張真值表卻有無限多個邏輯公式與之對應。 真值表相同的公式稱為邏輯等價(logically equivalent)的公式,記作 \(\equiv\)

例如下列真值表(即 OR):

\(A\) \(B\) 輸出
0 0 0
0 1 1
1 0 1
1 1 1

對應公式包括: \(\begin{array}{l} A \lor B \\ \lnot(\lnot A \land \lnot B) \\ B \lor A \\ \lnot(\lnot A \land \lnot B) \land (A \lor \lnot A) \\ \end{array}\)

真值表有兩大用途:

  1. 驗證邏輯等價:兩個公式的真值表逐列比對,全部相同即等價。

  2. 描述未知公式的行為:先列出所有輸入組合的期望輸出, 再想辦法找出符合的公式——這正是第 2 章的主題。

布林代數定律總表(延伸補充)

以下定律都可以用真值表逐一驗證,之後化簡公式時會反覆用到。 注意每條定律都有 \(\land\)\(\lor\)對偶版本:

定律名稱 \(\land\) 版本 \(\lor\) 版本
同一律(Identity) \(A \land 1 \equiv A\) \(A \lor 0 \equiv A\)
支配律(Domination) \(A \land 0 \equiv 0\) \(A \lor 1 \equiv 1\)
冪等律(Idempotent) \(A \land A \equiv A\) \(A \lor A \equiv A\)
交換律(Commutative) \(A \land B \equiv B \land A\) \(A \lor B \equiv B \lor A\)
結合律(Associative) \((A \land B) \land C \equiv A \land (B \land C)\) \((A \lor B) \lor C \equiv A \lor (B \lor C)\)
分配律(Distributive) \(A \land (B \lor C) \equiv (A \land B) \lor (A \land C)\) \(A \lor (B \land C) \equiv (A \lor B) \land (A \lor C)\)
吸收律(Absorption) \(A \land (A \lor B) \equiv A\) \(A \lor (A \land B) \equiv A\)
互補律(Complement) \(A \land \lnot A \equiv 0\) \(A \lor \lnot A \equiv 1\)
德摩根定律(De Morgan) \(\lnot(A \land B) \equiv \lnot A \lor \lnot B\) \(\lnot(A \lor B) \equiv \lnot A \land \lnot B\)
雙重否定(Double negation) \(\lnot\lnot A \equiv A\)

為什麼要學這些?

布林邏輯遍布所有程式語言。學會建構與化簡布林表達式, 能幫助你把真實問題轉譯成簡潔的程式。例如:

// 化簡前:巢狀條件,難讀又容易出錯
if (isWeekend) {
    if (!isRaining) { goHiking(); }
} else {
    if (isHoliday && !isRaining) { goHiking(); }
}

// 用布林代數化簡:(W && !R) || (!W && H && !R)
//   = !R && (W || (!W && H))      [提出公因子 !R]
//   = !R && (W || H)              [吸收律變形:W || (!W && H) = W || H]
if (!isRaining && (isWeekend || isHoliday)) { goHiking(); }

在硬體層面,化簡表達式代表更少的邏輯閘、更低的能耗與更快的運算(見第 3 章)。

本章重點

  • 數位裝置以二進位(\(1\)/TRUE/通電、\(0\)/FALSE/斷電)表示資料。

  • 命題是非真即假的敘述;命題變數承載其真假值。

  • 基本運算子:\(\lnot\)\(\land\)\(\lor\);衍生運算子:\(\oplus\)\(\to\)\(\leftrightarrow\) 都能用基本運算子改寫。

  • 真值表是公式行為的完整描述:一式一表,但一表多式(邏輯等價)。

  • 德摩根定律與分配律等基本定律是化簡與證明等價的核心工具。

尋找公式(Finding Formula)

上一章結尾提出了關鍵問題:給定一張期望輸出的真值表,如何產生對應的邏輯公式? 本章介紹兩種系統化方法(DNF 與 CNF),以及兩種化簡工具(代數定律與卡諾圖)。

析取範式(DNF, Disjunctive Normal Form)

析取範式(DNF):由一個或多個「合取項」(以 \(\land\) 連接的變數組) 用 \(\lor\) 連接而成的公式,其中 \(\lnot\) 只能直接出現在變數前面。 形式上:\((\cdots \land \cdots) \lor (\cdots \land \cdots) \lor \cdots\)

方法:針對真值表中每一個輸出為 1 的列:

  1. 把該列的輸入變數用 \(\land\) 連接(值為 0 的變數前面加 \(\lnot\)), 構成一個合取項——此項只在該列的輸入組合下為真;

  2. 把所有列的合取項用 \(\lor\) 連接起來。

\(A\) \(B\) \(C\) \(?\)
0 0 0 1
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 0
1 1 1 0

輸出為 1 的列共五列,每列各產生一個合取項: \[? \equiv (\lnot A \land \lnot B \land \lnot C) \lor (\lnot A \land \lnot B \land C) \lor (\lnot A \land B \land \lnot C) \lor (A \land \lnot B \land \lnot C) \lor (A \land \lnot B \land C)\] 這就是 DNF——正確,但看起來非常複雜!

合取範式(CNF, Conjunctive Normal Form)

合取範式(CNF):由一個或多個「析取項」(以 \(\lor\) 連接的變數組) 用 \(\land\) 連接而成的公式,其中 \(\lnot\) 只能直接出現在變數前面。 形式上:\((\cdots \lor \cdots) \land (\cdots \lor \cdots) \land \cdots\)

方法:針對每一個輸出為 0 的列:

  1. 把該列的輸入變數用 \(\land\) 連接(值為 0 的變數加 \(\lnot\))後整體取否定 ——意思是「排除這一種輸入組合」;

  2. 把所有這些否定項用 \(\land\) 連接。

沿用例題 2.1 的真值表,輸出為 0 的列只有三列(\(011\)\(110\)\(111\)): \[? \equiv \lnot(\lnot A \land B \land C) \land \lnot(A \land B \land \lnot C) \land \lnot(A \land B \land C)\]

因為 0 比 1 少,這個公式比 DNF 短——但它還不是 CNF: \(\lnot\) 出現在整個括號前,而不是只在變數前。

經驗法則:真值表中 1 少就用 DNF、0 少就用 CNF,得到的初始公式較短。

用德摩根定律完成 CNF

\[\lnot(A \land B) \equiv \lnot A \lor \lnot B \qquad\qquad \lnot(A \lor B) \equiv \lnot A \land \lnot B\] 口訣:否定往括號裡推:\(\land\)\(\lor\) 互換,每個變數加上/去掉否定。 定律可直接推廣到多個變數,例如 \(\lnot(A \land B \land C) \equiv \lnot A \lor \lnot B \lor \lnot C\)

把德摩根定律套用到上面三個項: \[\begin{array}{lcl} \lnot(\lnot A \land B \land C) & \equiv & (A \lor \lnot B \lor \lnot C) \\ \lnot(A \land B \land \lnot C) & \equiv & (\lnot A \lor \lnot B \lor C) \\ \lnot(A \land B \land C) & \equiv & (\lnot A \lor \lnot B \lor \lnot C) \\ \end{array}\] 於是得到真正的 CNF: \[? \equiv (A \lor \lnot B \lor \lnot C) \land (\lnot A \lor \lnot B \lor C) \land (\lnot A \lor \lnot B \lor \lnot C)\]

用分配律化簡

有了兩種「找公式」的方法之後,下一個任務是化簡。分配律是理想工具:

\[(A \land B) \lor (A \land C) \equiv A \land (B \lor C) \qquad\qquad (A \lor B) \land (A \lor C) \equiv A \lor (B \land C)\] 類比於數學中的提出公因式;反方向使用則是展開

把剛才的 CNF 一步步化簡(每一步右側註明使用的定律): \[\begin{array}{cl} & (A \lor \lnot B \lor \lnot C) \land (\lnot A \lor \lnot B \lor C) \land (\lnot A \lor \lnot B \lor \lnot C) \\[3pt] \equiv & \lnot B \lor \bigl((A \lor \lnot C) \land (\lnot A \lor C) \land (\lnot A \lor \lnot C)\bigr) \quad\text{【三項都含 $\lnot B$,用分配律提出】} \\[3pt] \equiv & \lnot B \lor \bigl((A \lor \lnot C) \land (\lnot A \lor (C \land \lnot C))\bigr) \quad\text{【後兩項提出 $\lnot A$】} \\[3pt] \equiv & \lnot B \lor \bigl((A \lor \lnot C) \land \lnot A\bigr) \quad\text{【$C \land \lnot C \equiv 0$(互補律),$\lnot A \lor 0 \equiv \lnot A$(同一律)】} \\[3pt] \equiv & \lnot B \lor \bigl((A \land \lnot A) \lor (\lnot C \land \lnot A)\bigr) \quad\text{【分配律展開,讓變數有機會相消】} \\[3pt] \equiv & \lnot B \lor (\lnot C \land \lnot A) \quad\text{【$A \land \lnot A \equiv 0$,$0 \lor X \equiv X$】} \\ \end{array}\] 最終結果:\(\boxed{\lnot B \lor (\lnot A \land \lnot C)}\),遠比原本的五項 DNF 或三項 CNF 精簡。

驗算:把化簡後的公式代回真值表,確認與原表一致:

\(A\) \(B\) \(C\) \(\lnot B \lor (\lnot A \land \lnot C)\)
0 0 0 1
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 0
1 1 1 0

✓ 與例題 2.1 完全一致

德摩根定律與分配律也可用來證明邏輯等價: 若能把一個公式一步步變形成另一個,兩者必然等價。 但這套代數方法有個缺點:很難判斷是否已化到最簡—— 這正是卡諾圖要解決的問題。

卡諾圖(Karnaugh Maps)

卡諾圖(Karnaugh map,K-map)是把真值表重新排列成二維格子的工具, 用「圈選相鄰的 1」找出邏輯表達式的最簡形式(minimal form)

卡諾圖由貝爾實驗室的 Maurice Karnaugh 於 1953 年提出, 是 Veitch 圖的改良版。它把「代數化簡」轉化成「視覺圖形辨識」, 在 4 個變數以內特別好用。

建構方式:把真值表的輸出填入格子,列與欄分別由部分輸入變數索引。 以兩變數為例:

\(A\) \(B\) \(?\)
0 0 1
0 1 0
1 0 1
1 1 1

\(\Longrightarrow\)

求最簡式的步驟:

  1. 把相鄰的 1 圈成邊長為 \(2^n\)(1、2、4、8……)的矩形方框

    • 方框可以跨越邊界繞回(wrap around)——上下邊相連、左右邊相連;

    • 方框可以(且應該)重疊——框越大,化出的項越簡單;

    • 不允許對角線圈選;方框內不可含 0。

  2. 對每個方框:把「框內值不變的變數」用 \(\land\) 連接(值恆為 0 的變數加 \(\lnot\));

  3. 把所有方框的表達式用 \(\lor\) 連接。

上例中:下排整列(\(A=1\),框內 \(B\) 有變、\(A\) 不變)給出項 \(A\); 左欄整欄(\(B=0\))給出項 \(\lnot B\)。答案:\(A \lor \lnot B\)

格雷碼(Gray Code)

當一側有兩個以上變數時,輸入值必須用二進位反射格雷碼 (binary-reflected Gray code)排列:相鄰的值只差一個位元

格雷碼生成法(講義版):從全 0 開始, 每次翻轉最右邊的、能產生新字串的位元\[00 \to 01 \to 11 \to 10\] (另一個等價方法是「反射法」:把 \(n\) 位元格雷碼上下鏡射,上半段前面補 0、下半段前面補 1, 就得到 \(n+1\) 位元格雷碼。)

為什麼一定要用格雷碼?卡諾圖的化簡原理是布林恆等式 \((X \land Y) \lor (X \land \lnot Y) \equiv X\): 兩個「只差一個變數」的項可以合併並消去那個變數。 格雷碼保證圖上相鄰的格子恰好只差一個位元, 所以「圈起相鄰格子」就等於「用代數合併相鄰項」。 若欄位照一般二進位順序 \(00,01,10,11\) 排列,\(01\)\(10\) 差兩個位元,圖就失效了。

四變數卡諾圖範例

列以 \(AB\) 索引、欄以 \(CD\) 索引,皆用格雷碼順序 \(00,01,11,10\)

三個方框的讀法:

  • 左欄整欄(4 格):框內 \(A\)\(B\) 都有變化,\(C=0\)\(D=0\) 不變 \(\Rightarrow\) \(\lnot C \land \lnot D\)

  • 中間 \(2\times2\) 方塊\(AB \in \{01,11\}\)\(CD \in \{00,01\}\)): \(B=1\)\(C=0\) 不變 \(\Rightarrow\) \(B \land \lnot C\)

  • 第一列左右兩端(wrap around 繞回相接,2 格): \(A=0\)\(B=0\)\(D=0\) 不變 \(\Rightarrow\) \(\lnot A \land \lnot B \land \lnot D\)

最簡式: \[(\lnot C \land \lnot D) \lor (B \land \lnot C) \lor (\lnot A \land \lnot B \land \lnot D)\]

回到例題 2.1/2.2 的三變數真值表(1 的位置:\(000,001,010,100,101\)), 列以 \(A\) 索引、欄以 \(BC\) 索引:

  • 左邊 \(2\times2\) 方塊\(BC \in \{00,01\}\)、兩列):只有 \(B=0\) 不變 \(\Rightarrow\) \(\lnot B\)

  • 第一列兩端\(BC=00\)\(BC=10\),繞回相接):\(A=0\)\(C=0\) 不變 \(\Rightarrow\) \(\lnot A \land \lnot C\)

最簡式:\(\lnot B \lor (\lnot A \land \lnot C)\) —— 與例題 2.2 用代數化簡得到的結果完全相同, 但 K-map 讓我們確信這已是最簡形式!

五個以上的變數

五變數最常見的做法:畫兩張四變數卡諾圖,分別代表第五個變數(\(E\))的兩個值, 然後在兩張圖之間「對齊/疊合」方框來化簡邏輯。

\(E = 0\) \(E = 1\)
  • \(E=0\) 圖中,中間兩列全為 1:\(B=1\) 不變、且此框只存在於 \(E=0\) \(\Rightarrow\) \(B \land \lnot E\)

  • 兩張圖都有\(2\times2\) 方塊(\(B=1\)\(C=0\))可以「疊合」: 因為它同時出現在 \(E=0\)\(E=1\),變數 \(E\) 被消去 \(\Rightarrow\) \(B \land \lnot C\)

最簡式:\((B \land \lnot E) \lor (B \land \lnot C)\)。 (還可再用分配律寫成 \(B \land (\lnot E \lor \lnot C)\)。)

本章重點

  • DNF:對每個輸出 1 的列做 \(\land\) 項,再全部 \(\lor\) 起來; CNF:對每個輸出 0 的列做「排除項」,再全部 \(\land\) 起來(需德摩根整理)。

  • 德摩根定律:否定推進括號時 \(\land \leftrightarrow \lor\) 互換。

  • 分配律 = 提公因式/展開,是代數化簡的主力;但代數法難以確認「已達最簡」。

  • K-map:格雷碼排列 + 圈 \(2^n\) 大小的方框(可繞回、可重疊) \(\Rightarrow\) 系統性地找出最簡式。

  • 5 變數:兩張 4 變數圖疊合;更多變數則需要其他演算法 (如 Quine–McCluskey 法,屬延伸閱讀)。

邏輯閘(Logic Gates)

什麼是邏輯閘?

邏輯閘(logic gate)是實作單一簡單布林函數(例如 \(A \land B\))的元件。 它是邏輯函數的抽象視圖:目前我們採取黑盒子(black box)觀點—— 只關心它的輸入輸出行為,不深究內部如何運作 (實體上它們由電晶體構成,本課程稍後會再回到這個主題)。

閘符號一覽

輸出(輸入 \(ab\)
5-8 符號 布林式 說明 00 01 10 11
NOT

(g) at (0,0) ; (g.in 1) – ++(-0.3,0) node[left]\(a\); (g.out) – ++(0.3,0) node[right]out;

\(\lnot a\) 反相器 \(a=0 \Rightarrow 1\)\(a=1 \Rightarrow 0\)
AND

(g) at (0,0) ; (g.in 1) – ++(-0.3,0) node[left]\(a\); (g.in 2) – ++(-0.3,0) node[left]\(b\); (g.out) – ++(0.3,0) node[right]out;

\(a \land b\) 全 1 才 1 0 0 0 1
OR

(g) at (0,0) ; (g.in 1) – ++(-0.3,0) node[left]\(a\); (g.in 2) – ++(-0.3,0) node[left]\(b\); (g.out) – ++(0.3,0) node[right]out;

\(a \lor b\) 有 1 就 1 0 1 1 1
NAND

(g) at (0,0) ; (g.in 1) – ++(-0.3,0) node[left]\(a\); (g.in 2) – ++(-0.3,0) node[left]\(b\); (g.out) – ++(0.3,0) node[right]out;

\(\lnot(a \land b)\) NOT-AND 1 1 1 0
NOR

(g) at (0,0) ; (g.in 1) – ++(-0.3,0) node[left]\(a\); (g.in 2) – ++(-0.3,0) node[left]\(b\); (g.out) – ++(0.3,0) node[right]out;

\(\lnot(a \lor b)\) NOT-OR 1 0 0 0
XOR

(g) at (0,0) ; (g.in 1) – ++(-0.3,0) node[left]\(a\); (g.in 2) – ++(-0.3,0) node[left]\(b\); (g.out) – ++(0.3,0) node[right]out;

\(a \oplus b\) 恰一個 1 0 1 1 0
XNOR

(g) at (0,0) ; (g.in 1) – ++(-0.3,0) node[left]\(a\); (g.in 2) – ++(-0.3,0) node[left]\(b\); (g.out) – ++(0.3,0) node[right]out;

\(\lnot(a \oplus b)\) 相同才 1 1 0 0 1

符號記憶要訣:

  • AND 是平頭 D 形;OR 是彎月尖頭形;

  • 輸出端的小圓圈(bubble)代表「取否定」: AND + 圓圈 = NAND,OR + 圓圈 = NOR,XOR + 圓圈 = XNOR;

  • XOR 在 OR 的輸入側多一道弧線。

NAND 與 NOR 特別重要:它們各自都是功能完備(functionally complete)的—— 任何布林表達式都可以只用其中一種閘實作出來, 因此是絕佳的建構基石(詳見第 4 章)。 XOR 與 XNOR 較不常用(它們容易由前面的閘組合出來),但仍需能夠辨認。

用電路實作邏輯

把邏輯表達式中的每個運算子換成對應的閘,即可建構出實作該式的電路。 複雜電路可由簡單電路組合而成;一條訊號線可以分支(branch)複製訊號送往多處。

先分別實作兩個子電路,再組合:

at (1.3,4.4) \(\lnot A \land B\); (a1) at (2.2,3.4) ; (n1) at (a1.in 1) ; (n1.in 1) – ++(-0.4,0) node[left]\(A\); (a1.in 2) – ++(-1.9,0) node[left]\(B\); (a1.out) – ++(0.4,0); at (1.3,1.6) \(\lnot(B \lor C)\); (o1) at (1.6,0.6) ; (n2) at (o1.out) ; (o1.in 1) – ++(-0.7,0) node[left]\(B\); (o1.in 2) – ++(-0.7,0) node[left]\(C\); (n2.out) – ++(0.4,0);

at (3.6,4.3) \((\lnot A \land B) \lor \lnot(B \lor C)\); (a1) at (2.6,3.3) ; (n1) at (a1.in 1) ; (o1) at (2.1,0.9) ; (n2) at (o1.out) ; (o2) at (5.6,2.1) ; (n1.in 1) – ++(-0.9,0) node[left]\(A\); (a1.in 2) – ++(-2.35,0) node[left]\(B\); (\((a1.in 2)+(-1.6,0)\)) circle (1.5pt); (\((a1.in 2)+(-1.6,0)\)) |- (o1.in 1); (o1.in 2) – ++(-1.0,0) node[left]\(C\); (a1.out) – ++(0.35,0) |- (o2.in 1); (n2.out) – ++(0.35,0) |- (o2.in 2); (o2.out) – ++(0.4,0) node[right]out;

注意 \(B\) 的訊號在進入 AND 閘之前分支(圖中的實心圓點), 同一份訊號同時送給 AND 閘與 OR 閘——不需要兩個 \(B\) 輸入。

最佳化:用最少的閘

同一個邏輯函數可以有很多種電路實作,我們追求用最少的閘

比較下列兩個輸出完全相同的電路:

\((\lnot A \lor (\lnot B \land \lnot C)) \land (B \lor (\lnot B \land \lnot C))\) \((\lnot A \land B) \lor \lnot(B \lor C)\)
共 8 個閘(若不分支則更多) 只需 4 個閘

左邊的電路有兩大問題:

  1. 公式本身沒化簡\((\lnot A \lor (\lnot B \land \lnot C)) \land (B \lor (\lnot B \land \lnot C))\) 可用分配律(把 \(\lnot B \land \lnot C\) 視為一個整體提出)化簡成 \((\lnot A \land B) \lor (\lnot B \land \lnot C)\), 再用德摩根把 \(\lnot B \land \lnot C\) 改寫成 \(\lnot(B \lor C)\)—— 後者只需 2 個閘(OR + NOT),比前者(2 個 NOT + 1 個 AND)省 1 個閘。

  2. 重複的閘沒有共用\((\lnot B \land \lnot C)\) 出現兩次, 卻蓋了兩份相同的子電路——把第一份的輸出分支即可,能再省 3 個閘。

實作流程建議:先用第 2 章的方法(代數定律或 K-map)把公式化到最簡, 再畫電路;畫完後檢查有沒有重複的子電路可以用分支共用。

Logisim:電路模擬工具

實體電路(尤其大規模生產時)非常昂貴,因此業界在實作前都會用模擬工具驗證設計。 本課程使用教育用模擬器 Logisim 設計並驗證電路。重點操作整理:

功能 說明
放置邏輯閘 左側探索窗格(explorer pane)的 Gates 資料夾; 常用閘也放在上方工具列。先放好所有閘,搭出電路「骨架」。
接線 編輯工具(edit tool)從元件接點拖曳到另一點; 拖曳既有導線可延長、縮短或分支。
輸入/輸出腳位 工具列上有輸入腳位(方形)輸出腳位(圓形), 接到電路的對應導線上。
測試 戳戳工具(poke tool)點擊輸入腳位切換 0/1, 觀察輸出是否符合預期。
屬性表 左下方的屬性表(attributes table)可修改元件設定: 閘的輸入數量、元件標籤、元件方向、腳位為輸入或輸出等。
子電路 Project \(>\) Add Circuit… 建立新電路; 在探索窗格單擊可把自訂電路當元件使用,雙擊可編輯它。 也能編輯元件外觀、重新排列輸入輸出腳位。

導線顏色的意義(除錯時非常重要):

顏色 意義
藍色 未知的 1 位元值(通常表示尚未接上輸入)
深綠色 值為 0 的 1 位元訊號
淺綠色 值為 1 的 1 位元訊號
紅色 錯誤(例如兩個輸出互相衝突、短路)

完整的 Logisim 使用手冊:http://www.cburch.com/logisim/docs.html

本章重點

  • 邏輯閘 = 單一布林函數的黑盒子實作;輸出端小圓圈代表否定。

  • 七個基本閘:NOT、AND、OR、NAND、NOR、XOR、XNOR; NAND 與 NOR 是功能完備的。

  • 電路實作 = 運算子逐一換成閘;訊號可分支共用。

  • 目標是最少閘數:先化簡公式,再共用重複的子電路。

  • Logisim 用於實作前的設計驗證;記住四種導線顏色的意義。

NAND 與功能完備性

功能完備(Functionally Complete)

一組運算子(或閘)是功能完備(functionally complete)的, 若任何布林表達式都能只用這組運算子表達。 NAND 單獨一個就是功能完備的——任何電路都可以只用 NAND 閘重新實作!

這帶來重大的實務優勢:只需要量產一種閘, 就能製造任何數位電路,使實體生產更有效率。

NAND(與 NOR)的功能完備性由 Henry M. Sheffer 於 1913 年在數學上證明, 因此 NAND 運算也稱為「Sheffer stroke」。 NOR 同樣功能完備,但業界標準是 NAND,因為其電晶體結構速度更快: 在 CMOS 製程中,NAND 把(較快的)nMOS 電晶體串聯、(較慢的)pMOS 並聯, NOR 則相反,所以 NAND「結構上比 NOR 快」。 知名教材《The Elements of Computing Systems》(nand2tetris) 正是從單一個 NAND 閘出發,一路蓋出一台完整的電腦。

雙重否定:加負號的自由

\[\lnot\lnot A \equiv A\] 兩個否定互相抵消。反過來用:可以隨時為任何表達式加上一對否定而不改變其意義。

雙重否定與德摩根定律結合,就成為把任何布林函數翻譯成「純 NAND 表達式」的強大工具。

\[A \lor B \;\xRightarrow{\text{雙重否定}}\; \lnot\lnot(A \lor B) \;\xRightarrow{\text{德摩根}}\; \lnot(\lnot A \land \lnot B)\] 最外層的 \(\lnot(\cdots \land \cdots)\) 正是一個 NAND! 所以 OR 閘等價於「兩個輸入都先反相的 NAND 閘」。

\[A \land B \equiv \lnot\lnot(A \land B)\] 內層的 \(\lnot(A \land B)\) 是 NAND,外層再加一個 NOT—— 即 AND 等價於「NAND 接一個反相器」。

NOT 也是 NAND

上面兩個實作都還含有「額外的」否定。沒關係——否定本身就是 NAND: 把同一個輸入接到 NAND 的兩隻腳即可: \[\lnot A \equiv \lnot(A \land A)\] (因為 \(A \land A \equiv A\),冪等律。)

因此例題 4.2 的 AND 若要「明確地」全用 NAND 寫出,就是: \[A \land B \equiv \lnot\bigl(\lnot(A \land B) \land \lnot(A \land B)\bigr)\]

三個基本閘的 NAND 實作總覽:

目標 純 NAND 寫法 需要的 NAND 數
\(\lnot A\) \(\lnot(A \land A)\) 1
\(A \land B\) \(\lnot(\lnot(A \land B) \land \lnot(A \land B))\) 2
\(A \lor B\) \(\lnot(\lnot(A \land A) \land \lnot(B \land B))\) 3

數 NAND 的技巧:把表達式整理成「否定只以 NAND 形式出現」之後, 數否定符號的個數就是所需 NAND 閘的數量。 每個 \(\lnot(\cdots \land \cdots)\) 是一個 NAND; 單獨的 \(\lnot X\) 是一個「輸入複製」的 NAND。

\[\begin{array}{cl} & (A \land B) \lor (B \land C) \\ \equiv & \lnot\lnot\bigl((A \land B) \lor (B \land C)\bigr) \quad\text{【雙重否定】} \\ \equiv & \lnot\bigl(\lnot(A \land B) \land \lnot(B \land C)\bigr) \quad\text{【德摩根】} \\ \end{array}\] 數一數否定:外層一個 \(\lnot(\cdots\land\cdots)\)、內層兩個 \(\lnot(\cdots\land\cdots)\) —— 共 3 個 NAND。電路如下(原電路 2 AND + 1 OR,NAND 版同樣 3 個閘):

(g1) at (2,3.1) ; (g2) at (2,0.9) ; (g3) at (4.6,2.0) ; (g1.in 1) – ++(-1.3,0) node[left]\(A\); (g1.in 2) – ++(-1.3,0) node[left]\(B\); (\((g1.in 2)+(-1.3,0)\)) circle (1.5pt); (\((g1.in 2)+(-1.3,0)\)) |- (g2.in 1); (g2.in 2) – ++(-1.3,0) node[left]\(C\); (g1.out) – ++(0.3,0) |- (g3.in 1); (g2.out) – ++(0.3,0) |- (g3.in 2); (g3.out) – ++(0.4,0) node[right]\(X\);

(g1) at (2,3.1) ; (g2) at (2,0.9) ; (g3) at (4.6,2.0) ; (g1.in 1) – ++(-1.3,0) node[left]\(A\); (g1.in 2) – ++(-1.3,0) node[left]\(B\); (\((g1.in 2)+(-1.3,0)\)) circle (1.5pt); (\((g1.in 2)+(-1.3,0)\)) |- (g2.in 1); (g2.in 2) – ++(-1.3,0) node[left]\(C\); (g1.out) – ++(0.3,0) |- (g3.in 1); (g2.out) – ++(0.3,0) |- (g3.in 2); (g3.out) – ++(0.4,0) node[right]\(X\);

推泡泡(Bubble Pushing)

視覺的角度看 NAND 實作:把每個否定視為一顆泡泡(bubble) ——就是 NOT、NAND、NOR 閘尖端的小圓圈。

推泡泡(bubble pushing)是把德摩根定律直接套用在電路圖上的技巧: \[\underbrace{\lnot(A \land B) \equiv \lnot A \lor \lnot B}_{\text{NAND } \equiv \text{ 輸入反相的 OR}} \qquad\qquad \underbrace{\lnot(A \lor B) \equiv \lnot A \land \lnot B}_{\text{NOR } \equiv \text{ 輸入反相的 AND}}\] 把泡泡從閘的輸出端「推」到輸入端(或反向)時,\(\land\) 閘與 \(\lor\) 閘互換。

圖示:NAND 的兩種畫法(左)與 NOR 的兩種畫法(右):

(g) at (0,0) ; (g.in 1) – ++(-0.3,0); (g.in 2) – ++(-0.3,0); (g.out) – ++(0.3,0); at (2.1,0) \(\equiv\); (h) at (4.2,0) ; at (\((h.in 1)+(-0.11,0)\)) ; at (\((h.in 2)+(-0.11,0)\)) ; (\((h.in 1)+(-0.22,0)\)) – ++(-0.3,0); (\((h.in 2)+(-0.22,0)\)) – ++(-0.3,0); (h.out) – ++(0.3,0);

(g) at (0,0) ; (g.in 1) – ++(-0.3,0); (g.in 2) – ++(-0.3,0); (g.out) – ++(0.3,0); at (2.1,0) \(\equiv\); (h) at (4.2,0) ; at (\((h.in 1)+(-0.11,0)\)) ; at (\((h.in 2)+(-0.11,0)\)) ; (\((h.in 1)+(-0.22,0)\)) – ++(-0.3,0); (\((h.in 2)+(-0.22,0)\)) – ++(-0.3,0); (h.out) – ++(0.3,0);

使用方法:已有一個只含 AND、OR、NOT 的化簡電路時, 從輸出端開始往回走,在適當處推泡泡或成對加泡泡(雙重否定), 即可合成等價的 NAND 電路。以 \((A \land B) \lor (C \land D)\) 為例:

(g1) at (0,1.5) ; (g2) at (0,-0.4) ; (g3) at (2.3,0.55) ; (g1.in 1) – ++(-0.3,0); (g1.in 2) – ++(-0.3,0); (g2.in 1) – ++(-0.3,0); (g2.in 2) – ++(-0.3,0); (g1.out) – ++(0.2,0) |- (g3.in 1); (g2.out) – ++(0.2,0) |- (g3.in 2); (g3.out) – ++(0.3,0);

(g1) at (0,1.5) ; (g2) at (0,-0.4) ; (g3) at (2.6,0.55) ; at (\((g3.in 1)+(-0.11,0)\)) ; at (\((g3.in 2)+(-0.11,0)\)) ; (g1.in 1) – ++(-0.3,0); (g1.in 2) – ++(-0.3,0); (g2.in 1) – ++(-0.3,0); (g2.in 2) – ++(-0.3,0); (g1.out) – ++(0.2,0) |- (\((g3.in 1)+(-0.22,0)\)); (g2.out) – ++(0.2,0) |- (\((g3.in 2)+(-0.22,0)\)); (g3.out) – ++(0.3,0);

(g1) at (0,1.5) ; (g2) at (0,-0.4) ; (g3) at (2.6,0.55) ; (g1.in 1) – ++(-0.3,0); (g1.in 2) – ++(-0.3,0); (g2.in 1) – ++(-0.3,0); (g2.in 2) – ++(-0.3,0); (g1.out) – ++(0.2,0) |- (g3.in 1); (g2.out) – ++(0.2,0) |- (g3.in 2); (g3.out) – ++(0.3,0);

步驟解讀:(1) 在兩個 AND 的輸出與 OR 的輸入之間各加一對泡泡 (雙重否定,不改變功能)——AND+泡泡成為 NAND; (2) 「輸入帶泡泡的 OR」依德摩根定律就是 NAND,直接改畫成 NAND。 完成:3 個 NAND,與例題 4.3 的代數推導一致。

NAND 電路的化簡

NAND 化最好在公式階段先化簡;但電路畫好後仍有兩招可用:

  1. 移除連續兩個作為雙重否定的 NAND: 兩個串接的「NOT 型 NAND」(輸入綁在一起)互相抵消,可整段拿掉。

  2. 合併作用相同的 NAND: 兩個輸入完全相同的 NAND 是重複的——留一個,把它的輸出分支給所有用到的地方。

NAND 板(NAND Boards):實驗室硬體

實驗課將把電路設計轉移到實體的 NAND 板上。板子的構造:

元件 說明
4 個輸入開關 每個開關未按下時輸出 0;各附 4 個複製輸出腳位, 方便把同一輸入送到多個閘。
16 個 NAND 閘 每個 NAND 有 \(A\)\(B\) 輸入腳位(各附複製腳位)、 一個顯示輸出值的 LED,以及 4 個複製輸出腳位
16 個常數 1 腳位 提供恆為 1 的訊號(例如把 NAND 當 NOT 用時可派上用場: \(\lnot(A \land 1) \equiv \lnot A\))。

實作忠告:上板子之前先在紙上規劃好哪個邏輯 NAND 對應板上哪個實體 NAND、 訊號怎麼走線——否則很快就會變成一團理不清的電線。 建議先畫好 NAND 電路圖並為每個閘編號(NAND 1、NAND 2、…), 再對應到板上的實體位置。第一次實驗課前請先觀看 NAND 板介紹影片。

本章重點

  • NAND 功能完備:\(\lnot A \equiv \lnot(A\land A)\)(1 個), \(A \land B\)(2 個),\(A \lor B\)(3 個)。

  • 雙重否定讓我們「免費」加負號;德摩根把 \(\lnot(\lor)\)\(\lnot(\land)\) 互換 ——兩者聯手可把任何公式改寫成純 NAND 形式。

  • 整理好的公式中,否定的個數 = 所需 NAND 的個數

  • 推泡泡 = 在電路圖上做德摩根:泡泡穿過閘時 AND \(\leftrightarrow\) OR 互換。

  • NAND 是業界標準(比 NOR 結構上更快);實驗課的 NAND 板有 4 個開關、16 個 NAND、16 個常數 1 腳位。

綜合練習題(附詳解)

練習 1:命題判斷

下列哪些是命題? (a)「\(3 + 4 = 8\)」 (b)「現在幾點?」 (c)「把門關上。」 (d)「所有偶數都能被 2 整除。」 (e)「\(x + 1\)

(a) ✓ 是命題(雖然是假的——命題不必為真,只需能判斷真假)。 (b) ✗ 疑問句無真假值。 (c) ✗ 祈使句無真假值。 (d) ✓ 是命題(且為真)。 (e) ✗ 只是運算式,沒有斷言任何事;改成「\(x + 1 = 5\)」才是(在 \(x\) 給定後的)命題。

練習 2:用真值表驗證 \(A \to B \equiv \lnot A \lor B\)

\(A\) \(B\) \(A \to B\) \(\lnot A\) \(\lnot A \lor B\)
0 0 1 1 1
0 1 1 1 1
1 0 0 0 0
1 1 1 0 1

第 3 欄與第 5 欄完全相同,故兩式邏輯等價。✓

練習 3:完成真值表

計算 \(\lnot(A \oplus B) \lor C\) 的完整真值表。

先算 \(A \oplus B\),取否定後再與 \(C\) 做 OR:

\(A\) \(B\) \(C\) \(A \oplus B\) \(\lnot(A \oplus B)\) \(\lnot(A \oplus B) \lor C\)
0 0 0 0 1 1
0 0 1 0 1 1
0 1 0 1 0 0
0 1 1 1 0 1
1 0 0 1 0 0
1 0 1 1 0 1
1 1 0 0 1 1
1 1 1 0 1 1

技巧:\(\lnot(A \oplus B)\) 就是 XNOR——「\(A\)\(B\) 相同」時為 1。

練習 4:DNF 與 CNF

給定真值表:輸出在 \((A,B) = (0,1)\)\((1,0)\) 時為 1,其餘為 0。 分別寫出 DNF 與 CNF。

(這正是 XOR!)

DNF(看輸出 1 的列): \((\lnot A \land B) \lor (A \land \lnot B)\)

CNF(看輸出 0 的列,即 \(00\)\(11\)): \[\lnot(\lnot A \land \lnot B) \land \lnot(A \land B) \xRightarrow{\text{德摩根}} (A \lor B) \land (\lnot A \lor \lnot B)\] 兩式都等價於 \(A \oplus B\)——與第 1 章「\((\lnot A \lor \lnot B) \land (A \lor B)\)」 的寫法一致(交換律)。

練習 5:代數化簡

用布林代數定律化簡 \((A \land B) \lor (A \land \lnot B) \lor (\lnot A \land B)\)

\[\begin{array}{cl} & (A \land B) \lor (A \land \lnot B) \lor (\lnot A \land B) \\ \equiv & \bigl(A \land (B \lor \lnot B)\bigr) \lor (\lnot A \land B) \quad\text{【前兩項提出 $A$(分配律)】} \\ \equiv & A \lor (\lnot A \land B) \quad\text{【互補律 $B \lor \lnot B \equiv 1$;同一律 $A \land 1 \equiv A$】} \\ \equiv & (A \lor \lnot A) \land (A \lor B) \quad\text{【$\lor$ 對 $\land$ 的分配律】} \\ \equiv & A \lor B \quad\text{【互補律;同一律】} \\ \end{array}\] 答案:\(A \lor B\)。 (直覺檢查:原式涵蓋「\(A\) 真」的兩種情形與「\(B\) 真而 \(A\) 假」——合起來就是 \(A \lor B\)。)

練習 6:卡諾圖化簡

用 K-map 求下列真值表的最簡式(輸出 1 的輸入組合: \(ABCD \in \{0000, 0001, 0011, 0010, 1000, 1001, 1011, 1010, 0101, 1101\}\))。

填圖(列 \(AB\)、欄 \(CD\),格雷碼順序):

  • 第一列(\(AB=00\))與最後一列(\(AB=10\)上下繞回合成 \(2\times4\) 大框(8 格): 框內 \(A\)\(C\)\(D\) 都有變化,只有 \(B=0\) 不變 \(\Rightarrow\) \(\lnot B\)

  • \(CD=01\) 整欄(4 格,含 \(0101\)\(1101\)): 框內 \(A\)\(B\) 都有變化,\(C=0\)\(D=1\) 不變 \(\Rightarrow\) \(\lnot C \land D\)。 注意這一欄與上面的大框重疊了兩格——重疊讓兩個框都能取到最大, 正是「方框應盡量大、可重疊」的威力。

最簡式:\(\boxed{\lnot B \lor (\lnot C \land D)}\)

練習 7:閘數計算

(a) 直接按照公式 \((\lnot A \land \lnot B) \lor (\lnot A \land C)\) 畫電路需要幾個閘? (b) 先化簡再畫呢?

(a) 直接實作:\(\lnot A\) 出現兩次(分支共用算 1 個 NOT)、\(\lnot B\) 1 個 NOT、 2 個 AND、1 個 OR,共 5 個閘

(b) 用分配律提出 \(\lnot A\)\(\lnot A \land (\lnot B \lor C)\) —— 1 個 NOT(\(A\))+ 1 個 NOT(\(B\))+ 1 個 OR + 1 個 AND = 4 個閘

練習 8:NAND 化

\(\lnot A \land B\) 改寫成只用 NAND 的表達式,並數出所需 NAND 數。

\[\begin{array}{cl} & \lnot A \land B \\ \equiv & \lnot\lnot(\lnot A \land B) \quad\text{【雙重否定】} \\ \equiv & \lnot\bigl(\underbrace{\lnot(\lnot A \land B)}_{\text{NAND}}\bigr) \\ \end{array}\] 逐層拆解:\(\lnot A\) 是 1 個 NAND(\(\lnot(A \land A)\)); \(\lnot(\lnot A \land B)\) 是第 2 個 NAND; 最外層的 \(\lnot X\)\(X\) 為前式)是第 3 個 NAND(\(\lnot(X \land X)\))。 完整寫法: \[\lnot\Bigl(\lnot\bigl(\lnot(A \land A) \land B\bigr) \land \lnot\bigl(\lnot(A \land A) \land B\bigr)\Bigr)\]3 個 NAND——恰等於整理後否定符號的個數。✓

練習 9:NOR 的功能完備性

仿照 NAND 的做法,證明 NOR(\(\lnot(A \lor B)\))也是功能完備的。

只需用 NOR 做出 NOT、OR、AND 三個基本閘: \[\begin{array}{lll} \textbf{NOT:} & \lnot A \equiv \lnot(A \lor A) & \text{(1 個 NOR,冪等律)} \\[3pt] \textbf{OR:} & A \lor B \equiv \lnot\lnot(A \lor B) \equiv \lnot\bigl(\lnot(A \lor B) \lor \lnot(A \lor B)\bigr) & \text{(2 個 NOR:NOR + NOT)} \\[3pt] \textbf{AND:} & A \land B \equiv \lnot\lnot(A \land B) \equiv \lnot(\lnot A \lor \lnot B) & \text{(3 個 NOR:兩個 NOT + NOR)} \\ \end{array}\] 由於 \(\{\lnot, \land, \lor\}\) 功能完備(DNF/CNF 保證任何真值表都可表達), 而三者都能用 NOR 構成,故 NOR 單獨功能完備。\(\blacksquare\) (與 NAND 恰成對偶:NAND 做 AND 要 2 個、做 OR 要 3 個;NOR 相反。)

練習 10:用 NAND 實作 XOR

\(A \oplus B\) 的純 NAND 實作,目標 4 個 NAND。

從等價式出發(令 \(N = \lnot(A \land B)\),即第 1 個 NAND 的輸出): \[A \oplus B \equiv (A \lor B) \land \lnot(A \land B) \equiv (A \land \lnot(A \land B)) \lor (B \land \lnot(A \land B))\] (第二步:把 \(\lnot(A\land B)\) 分配進 \((A \lor B)\)\(A \land \lnot(A \land B) \equiv A \land \lnot B\)\(B \land \lnot(A \land B) \equiv B \land \lnot A\),正是 XOR 的 DNF。)

再套雙重否定與德摩根: \[\equiv \lnot\bigl(\lnot(A \land N) \land \lnot(B \land N)\bigr)\] 四個 NAND 分別是:

  1. \(N = \lnot(A \land B)\)

  2. \(P = \lnot(A \land N)\)

  3. \(Q = \lnot(B \land N)\)

  4. 輸出 \(= \lnot(P \land Q)\)

(n1) at (2.2,2.0) ; (n2) at (4.6,3.0) ; (n3) at (4.6,1.0) ; (n4) at (7.0,2.0) ; (n2.in 1) – (n2.in 1 -| 0,0) node[left]\(A\); (n2.in 1 -| 0.9,0) circle (1.5pt); (n2.in 1 -| 0.9,0) |- (n1.in 1); (n3.in 2) – (n3.in 2 -| 0,0) node[left]\(B\); (n3.in 2 -| 0.9,0) circle (1.5pt); (n3.in 2 -| 0.9,0) |- (n1.in 2); (n1.out) – ++(0.25,0); (\((n1.out)+(0.25,0)\)) circle (1.5pt); (\((n1.out)+(0.25,0)\)) |- (n2.in 2); (\((n1.out)+(0.25,0)\)) |- (n3.in 1); (n2.out) – ++(0.25,0) |- (n4.in 1); (n3.out) – ++(0.25,0) |- (n4.in 2); (n4.out) – ++(0.4,0) node[right]\(A \oplus B\);

驗證(真值表):\(A{=}B\) 時輸出 0;\(A{\ne}B\) 時輸出 1。✓

附錄:速查表

名詞中英對照

英文 中文 英文 中文
proposition 命題 disjunctive normal form (DNF) 析取範式
propositional variable 命題變數 conjunctive normal form (CNF) 合取範式
negation / complement 否定/補 distributivity 分配律
conjunction 合取(AND) Karnaugh map (K-map) 卡諾圖
disjunction 析取(OR) Gray code 格雷碼
exclusive or (XOR) 互斥或 minimal form 最簡形式
implication 蘊含 logic gate 邏輯閘
equivalence 等價 functionally complete 功能完備
truth table 真值表 bubble pushing 推泡泡
compound proposition 複合命題 branching (a signal) (訊號)分支
logically equivalent 邏輯等價 double negation 雙重否定
De Morgan’s laws 德摩根定律 propagation 傳遞

六個運算子速查

\(A\) \(B\) \(\lnot A\) \(A \land B\) \(A \lor B\) \(A \oplus B\) \(A \to B\) \(A \leftrightarrow B\)
0 0 1 0 0 0 1 1
0 1 1 0 1 1 1 0
1 0 0 0 1 1 0 0
1 1 0 1 1 0 1 1

衍生運算子的基本式改寫: \(A \oplus B \equiv (\lnot A \lor \lnot B) \land (A \lor B)\)\(A \to B \equiv \lnot A \lor B\)\(A \leftrightarrow B \equiv (\lnot A \lor B) \land (\lnot B \lor A)\)

NAND 實作速查

目標 NAND 寫法 NAND 數
\(\lnot A\) \(\lnot(A \land A)\) 1
\(A \land B\) \(\lnot(\lnot(A \land B) \land \lnot(A \land B))\) 2
\(A \lor B\) \(\lnot(\lnot(A \land A) \land \lnot(B \land B))\) 3
\(A \oplus B\) 見練習 10 4

參考資料

  • Kira Clements, COMSM1302 Week 1 lecture slides(1.1–1.4),University of Bristol.

  • Nisan & Schocken, The Elements of Computing Systems(nand2tetris),Ch. 1 Boolean Logic.

  • Wikipedia:NAND logicKarnaugh mapFunctional completeness.

  • All About Circuits,Logic Simplification With Karnaugh Maps.

  • Logisim 使用手冊:http://www.cburch.com/logisim/docs.html

  • Sheffer, H. M.(1913),NAND 功能完備性的原始證明.