根據上面的加法,我們覺得的確門邏輯能解決這種加法的進位問題。可是減法呢?
減法涉及到借位,並且還要判斷位數能不能借,不能借得向更高的位去借,這種邏輯貌似門實現起來復雜度相當之高?其實不然
如何避免這種復雜的借位,最好的辦法,向最高位的再高一位借一位,那么就涉及不到那么多位的借位了。也就是說8位,我們借第九位的一位。所以得到
253-176=77的情況下,我們可以借個1000,因為減1000只涉及到最高位的門邏輯,然后用999減去176,因為999和176都是三位,用相同數量的門電路可以實現了,結果再加1.而176我們就叫做999的補數。
現在結果編程計算253+999-176+1-1000的情況。
但是如果是176-253呢?你可能會想到跟前面一樣,176+999-253+1-1000,但是923-1000導致了借位,這樣我們只操作最高位高一位的門邏輯是無法實現的。我們不如直接176+999-253-999,讓它們都用相同數據量級的門邏輯計算,不過922-999這一步我們把它變成999-922,然后再加個負符號。
現在我們演化成二進制來看看。
253-176 變成二進制位
1 1 1 1 1 1 0 1
-1 0 1 1 0 0 0 0
—————————
? ? ? ? ? ? ? ?
第一步、我們使用11111111(255)減去減數:
1 1 1 1 1 1 1 1
-1 0 1 1 0 0 0 0
--------------------
0 1 0 0 1 1 1 1
這種計算對於門電路來說很簡單,只需要對減數求反,將0變成1,1變成0.
第二步、把被減數和剛才我們求得的對1的補數相加:
1 1 1 1 1 1 0 1
+0 1 0 0 1 1 1 1
-------------------
1 0 1 0 0 1 1 0 0
第三步、對上面結果+1
1 0 1 0 0 1 1 0 0
+ 1
-----------------------
1 0 1 0 0 1 1 0 1
第四步,減去100000000(256)
1 0 1 0 0 1 1 0 1
- 1 0 0 0 0 0 0 0 0
-----------------------
1 0 0 1 1 0 1
即等於77.
現在我們來算下176-253
二進制表示為
1 0 1 1 0 0 0 0
- 1 1 1 1 1 1 0 1
--------------------
? ? ? ? ? ? ? ?
第一步,用11111111減去減數,得到對1的補數
1 1 1 1 1 1 1 1
- 1 1 1 1 1 1 0 1
-------------------
0 0 0 0 0 0 1 0
第二步,將減數對1的補數與被減數相加:
1 0 1 1 0 0 0 0
+0 0 0 0 0 0 1 0
---------------------
1 0 1 1 0 0 1 0
第三步、用11111111減去結果
1 1 1 1 1 1 1 1
- 1 0 1 1 0 0 1 0
--------------------
0 1 0 0 1 1 0 1
結果是77,但是答案應該是-77
現在我們可以來改造上面一章的加法器了,為了不過於復雜,我們先涉及減數小於被減數的操作。
上一章我們的加法器是這樣的:
我們得增設一個標識,來表明它是一個加法還是減法。我們的目的是做一個既能做加法,也能做減法的邏輯器。
首先我們得對B進行取反,且僅當減法的時候進行取反,這樣就不會影響到加法,
我們首先想下異或門的工作方式:
XOR | 0 | 1 |
0 | 0 | 1 |
1 | 1 | 0 |
改造圖如下:
取反就是我們的加法減法標識,我們定義標識為0時是加法,1是減法。當0加法的時候,輸入和輸出是不變的,如果是1減法的時候,那么正好是一個取反的狀態。
我們將8個異或門組成的器件,稱為求補器:
現在我們組合的連接如下:
SUB就是我們的加法減法的標識位,0加法,1減法。在B輸入的時候,我們進行減法求反,達到被11111111減去的效果,通過最右邊的SUB來達到對減法結果加1的效果,對加法沒影響。通過最左邊的異或門和sub來達到上溢(大於255)/下溢(負數)的結果,SUB為0加法的時候,對輸出沒影響,CO為1代表大於255。當減法的時候,SBU為1,CO輸出1,這個門邏輯組合就會得到0,達到減去100000000的效果,如果CO輸出0,代表了負數(如5-8=9+1-10+5-8=9-8+5+1-10=6-10,被減數只要小於減數,最后推算的這個被減數6是無論如何十位是不可能得到1的)經過這個門邏輯組合就會得到1,所以這個1就是下溢(負號)的標識。
現在我們的減法器是做好了,那么接下來我們討論下這個負數如何在我們的二進制里面表示呢?
我們平常使用的系統都是在一定范圍內的數字,所以我們不用求無限大的數值表示。
比如我們現在需要表示-500到499之間的數。我們都要用正數表示,因為我們二進制系統不支持-這個符號。我們就用三位數來表示這些數字。
500表示-500,501表示-499......999表示-1,000表示0,001表示1......499表示499
這樣我們就形成了一個循環,好處是我們-1+1=0的情況用正數來表示999+1=1000,1由於是第四位,會被舍棄,就會得到結果0,
這種標記的方法稱為10的補數。
如果你有一個余額為143塊的賬戶,你用了78元。-78對10的補數是999-078+1=65(忽略溢出)。如果我們用超額的用了150塊,-150對10的補數是850,就等於915,就是新賬戶的余額,在我們的表示中就是-85塊。