
初见这关的时候卡了很久,上网找到的攻略又大多都是先入为主,以过关者的身份就一笔带过了,让初学者很难看明白。我在隔了两天终于理解本关后写下这篇教程。
无符号的八位二进制数(范围从0到255),想判断这样两个数的大小,我们可以通过A减去B的结果来进行判断。

便于直观理解的数轴
在门电路里,没有直接意义上的“减法”,只有“加法”,半加器和全加器,我们可以用A加上B的相反数来进行减法计算。

无符号小于电路图
电路图:如图所示,一个完整的A减去B的门电路图,八位加法器的输入1为A,输入2为~B,注意取反不等于相反数,所以在输入进位再补1。最后通过溢出进位来判断A和B的大小关系。
比如A是1(0000 0001),B是254(1111 1110),
B取反后是1(0000 0001),二者相加再补1得到结果为3(00000011)
此时溢出进位为0,不过A确实小于B,所以我们给电路输出加上一个非门,输出为1,代表A小于B。
比如A是254(1111 1110),B是1(0000 0001),
B取反后是254(1111 1110),二者相加再补1得到结果为509(1 1111 1101)
此时溢出进位为1,电路输出为0,代表A不小于B。
一些补充
Q1.为什么对B要先取反再补1,为什么不直接取负数?
A1.简单来说,是为了避免B为0的情况。复杂来说,虽然-B和(~B) + 1在数学上是等价的,但在计算机底层电路中,这两个形式做计算在进位Carry标志上是不同的。
Q2.为什么做完减法后要加一个非门?
A2.因为题目要求当A小于B时输出为1,加非门是为了满足题目要求。
Q3.254减去1明明就是253,你这个509是怎么回事?
A3.是的,直觉上254减1确实是253,用计算器计算也会得到253,但在计算器的底层电路中,509多出来的高位第九位是用来表示进位的,实际输出只会保留我们需要的位数部分,也就是253,二者只是视角不同。
有符号的八位二进制数(范围从-128到127),想判断这样两个数的大小,我们不仅要让二者相减判断溢出进位,更要判断二者本身的符号,比如二者都为正或者都为负的时候,可以沿用无符号小于的思路,但如果是一正一负的时候,我们就需要额外考虑了。

便于直观理解的数轴

有符号小于电路图
电路图:如图所示,电路图的上半部分是沿用无符号小于的思路,A减去B判断溢出进位。
下半部分我们用异或门对A和B的符号位(第八位)进行了异或计算,为了判断A和B到底是不是相同符号的。最后将两个结果再进行一次异或计算,得到电路输出。

异或门
比如A是-127(1000 0001),B是-1(1111 1111)
上半部分相减后得到结果为-126(1000 0010),没有溢出进位,结果为1。
下半部分二者异或1 XOR 1结果为0。
最终异或1 XOR 0结果为1,代表A小于B。
比如A是1(0000 0001),B是-1(1111 1111)
上半部分相减后得到结果为2(0000 0010),没有溢出进位,结果为1。
一般来说没有溢出是否就代表A比B小了?
再来看下半部分二者异或0 XOR 1得到结果为1。
最终异或 1 XOR 1得到结果为0,说明A不小于B。
一些补充
Q1.为什么我看其他攻略最后是用一个全加器将上下部分相连?
A1.因为全加器的总和位的本质就是对三个输入依次进行异或,重点不是全加器,而是异或。
Q2.为什么要对A和B的符号位进行异或?
A2.因为异或的本质是判断二者是否相同,不同就输出1,这能帮助我们判断A和B到底是同符号的还是不同符号的,如果同符号就沿用无符号小于的思路,如果不同符号就要在无符号小于的思路基础上取一次反。
判断大小这个问题确实不难,对于有基础的人来说也许一眼就搞定了,但对于新手来说,也许很难绕过一些弯子。
如果这篇教程有帮到你,麻烦点个赞让我看见。
如果这篇教程让你一头雾水,麻烦在评论区告诉我,好让我知道我的哪些表述是有待修改的。