只用 Nand 运算符来表示任意的布尔函数

68 阅读1分钟

要点

mindmap
      Root(布尔函数)
          A(总可以写成析取范式(DNF)的形式)
            B(DNF中只用到了 And/Or/Not 三种运算)
                C(Or 可以用 And/Not 来表示)
                D(Not 可以用 Nand 来表示)
                E(And 可以用 Nand 来表示)

正文

The Elements of Computing Systems 一书的附录 A 中提到

任何布尔函数都可以用只包含 Nand 运算符的表达式表示

我们可以通过以下几步来证明它。

第一步:任何布尔函数都可以写成析取范式(DNF, Disjunctive Normal Form)的形式

我们通过具体的例子来进行说明。假设一个布尔函数 f(a,b,c)f(a,b,c) 的真值表如下

aabbccf(a,b,c)f(a, b, c)
00000011
00001111
00110000
00111111
11000011
11001100
11110011
11111100

在真值表的某些行中,f(a,b,c)f(a, b, c) 值为 11,我们可以为所有这样的行找到对应的最小项(minterm)。例如

  • a=0,b=0,c=0a=0,b=0,c=0 那一行,对应的最小项是 f0(a,b,c)=¬a¬b¬cf_0(a,b,c)=\neg{a} \land \neg{b} \land \neg{c}
  • a=1,b=1,c=0a=1,b=1,c=0 那一行,对应的最小项是 f6(a,b,c)=ab¬cf_6(a,b,c)=a \land b \land \neg{c}

于是,我们可以将 f(a,b,c)f(a,b,c) 写成一些最小项(minterm)的 或(\lor),具体如下

f(a,b,c)=f0(a,b,c)f1(a,b,c)f3(a,b,c)f4(a,b,c)f6(a,b,c)f(a,b,c)=f_0(a,b,c)\lor f_1(a,b,c)\lor f_3(a,b,c)\lor f_4(a,b,c)\lor f_6(a,b,c)

其中

  • f0(a,b,c)=¬a¬b¬cf_0(a,b,c)=\neg{a} \land \neg{b} \land \neg{c}
  • f1(a,b,c)=¬a¬bcf_1(a,b,c)=\neg{a} \land \neg{b} \land c
  • f3(a,b,c)=¬abcf_3(a,b,c)=\neg{a} \land b \land c
  • f4(a,b,c)=a¬b¬cf_4(a,b,c)=a \land \neg{b} \land \neg{c}
  • f6(a,b,c)=ab¬cf_6(a,b,c)=a \land b \land \neg{c}

基于以上结果,我们可以画一个详细的真值表 ⬇️ (aa,bb,cc 三列是输入,其他列是计算结果)

aabbccf(a,b,c)f(a, b, c)f0(a,b,c)f_0(a, b, c)f1(a,b,c)f_1(a, b, c)f3(a,b,c)f_3(a, b, c)f4(a,b,c)f_4(a, b, c)f6(a,b,c)f_6(a, b, c)
000000111100000000
000011110011000000
001100000000000000
001111110000110000
110000110000001100
110011000000000000
111100110000000011
111111000000000000

第二步:任何布尔函数都可以用只包含与(And)/或(Or)/非(Not)运算的布尔表达式表示

在第一步中,我们通过一个例子说明了任何布尔函数都可以写成 析取范式(即 最小项)的形式,而 最小项 中只用到了 非(Not) 运算和 与(And) 运算。在析取范式中,我们是用 或(Or) 运算将 最小项 连接起来的,所以 析取范式 中只用到了 与(And)/或(Or)/非(Not) 三种运算。所以任何布尔函数都可以用只包含 与(And)/或(Or)/非(Not)运算 的布尔表达式表示。

第三步:任何布尔函数都可以用只包含非(Not)和与(And)运算符的布尔表达式表示

或(Or)运算的真值表如下

aabbaba\lor b
000000
001111
110011
111111

不难验证,aba\lor b 的真值表和 ¬(¬a¬b)\neg{(\neg{a}\land \neg{b})} 的真值表相同 ⬇️ (aa,bb 两列是输入,其他列是计算结果)

aabb¬a\neg{a}¬b\neg{b}¬a¬b\neg{a}\land \neg{b}¬(¬a¬b)\neg{(\neg{a}\land \neg{b})}
000011111100
001111000011
110000110011
111100000011

所以在析取范式的基础上,我们可以用 非(Not)/与(And) 运算来替代所有的 或(Or) 运算,这样我们就可以只用 非(Not)与(And) 运算符来表达任意的布尔函数。

第四步:任何布尔函数都可以用只包含 Nand 运算符的表达式表示

在第三步中,我们已经证明了任何布尔函数都可以用只包含 非(Not)与(And) 运算符的布尔表达式表示。所以如果我们能用 Nand 运算符来替代 非(Not) 以及 与(And) 运算符,那么就可以证明任何布尔函数都可以用只包含 Nand 运算符的表达式表示。

非(Not) 运算符的真值表如下

aa¬a\neg{a}
0011
1100

因为 Nand(a,b)=¬(ab)\text{Nand}(a, b)=\neg{(a\land b)},可以得出 Nand 运算符的真值表如下 ⬇️

aabbNand(a,b)\text{Nand}(a, b)
000011
001111
110011
111100

所以 ¬a=Nand(a,a)\neg{a}=\text{Nand}(a, a),可见 Nand 运算符可以替代 非(Not) 运算符。

因为

ab=¬(¬(ab))=¬Nand(a,b)a\land b=\neg{(\neg{(a\land b)})}=\neg{\text{Nand}(a,b)}

非(Not) 运算符可以用 Nand 运算符来表示,所以 Nand 运算符可以替代 与(And) 运算符。

至此,我们证明了

任何布尔函数都可以用只包含 Nand 运算符的表达式表示

总结

我们通过如下的方式证明了,任何布尔函数都可以用只包含 Nand 运算符的表达式表示 ⬇️

  1. 任何布尔函数可以写成对应的 DNF
  2. DNF 中只包含 And/Or/Not 运算符(用 And/Or/Not 运算符可以表示任意的布尔函数)
  3. Or 运算符可以用 AndNot 运算符来替代 (用 And/Not 运算符可以表示任意的布尔函数)
  4. Not 运算符和 And 运算符都可以用 Nand 运算符来替代 (用 Nand 运算符可以表示任意的布尔函数)

可以把证明中关于 And/Or/Not 的部分写成 ⬇️

  • Not: ¬a=Nand(a,a)\neg{a}=\text{Nand}(a,a)
  • And: ab=¬Nand(a,b)=Nand(Nand(a,b),Nand(a,b))a\land b=\neg{\text{Nand}(a,b)}=\text{Nand}(\text{Nand}(a,b),\text{Nand}(a,b))
  • Or: ab=¬(¬a¬b)=Nand(Nand(a,a),Nand(b,b))a\lor b= \neg{(\neg{a}\land \neg{b})}=\text{Nand}(\text{Nand}(a,a),\text{Nand}(b,b))

参考资料