二進位制補碼的一些思考

2022-03-02 14:55:55 字數 2730 閱讀 4262

最近都一直在看幾本關於計算機組成原理方面的大作:《code: the hidden language of computer hardware and software》,《computer system: a programer perspective》,《introduction to computer systems》,算是補充了自己作為乙個非計算機專業的程式設計師在這方面的缺失。特別是看了《code》中關於加法器與減法器實現的章節後,對於二進位制補碼有了乙個感性的認識。

在計算機的歷史中,曾經出現過三種表示負數的二進位制方法。第一種是直接用乙個符號位。第二種是用反碼,即對乙個整數的全部位取反則得到這個數的負數。而最後的一種方式就是二進位制補碼(two』s complement)。

但是為什麼現在的計算機都要採用二進位制補碼這種方式呢?在所有知識的背後,要做到知其然的同時,更要做到知其所以然,這樣才能做到真正的理解。其實採用二進位制補碼的原因很簡單,簡單,高效。

要真正理解這背後的原因,首先我們需要理解,計算機是如何做加法的。

我們知道,當乙個與門和乙個異或門組合在一起的時候,就可以形成乙個接受兩個1bit的輸入,並且輸出其相加的和的結果和進製的半加器。

而當兩個這樣的半加器再與乙個或門組合在一起時,就可以形成乙個接受兩個1bit輸入,1bit進製輸入,輸出加和輸出和進製輸出的全加器。

而當n個這樣的全加器組合在一齊時,就可以形成乙個能計算兩個n為二進位制數相加的加法器。

理解了上面的實現方式之後,我們就可以做出一台上古時代用於計算二進位制加法的加法器:

當我們實現了加法器之後,理所當然的,我們希望同樣能實現減法。但我們知道減法與加法相比,是不一樣的機制的。加法只有向前進製,而減法呢?減法則有可能會向前借位,同時,前一位又可能再向前借位,這是一種十分麻煩的機制。那麼有什麼辦法可以解決這個這麼麻煩的問題呢?上古時代的天才們就開始想,能不能把減法轉換為加法,那麼就可以借用簡單的加法器來進行減法運算呢?於是一種基於補碼的使減法變成加法,通過加法器來運算的方法就誕生了。

首先,可以看乙個在《code》裡面舉的例子:

253 – 176 = ???

可以看到,這個減法運算在個位的時候,就需要向前借位了,十分麻煩。

但是我們可以轉變一下思路,首先這是乙個三位數,三位數的最大值是999。因此我們先用999減去減數176

999 – 176 = 823

然後,用被減數253加上上面求出來的這個值823

253 + 823 = 1076

然後把這個值加1再減去1000,這樣就得到了77。噢,這個不正是我們需要的結果77嗎?

大家可以看到,在這個過程中,我們雖然用到了減法,但是我們沒有用到借位,並且,若我們把這種方法模擬到二進位製上,我們就會發現,上面的幾個做減法的步驟,完全可以通過簡單的閘電路來實現,而不需要真正地進行運算。好,我們就用同樣上面的數字來進行一下二進位制的運算。

253 – 176 轉換為二進位制則是:1111 1101 – 1011 0000 = ???? ????

第一步,用8位二進位制數中的最大值,即1111 1111,減去減數1011 0000

1111 1111 – 1011 0000 = 0100 1111

然後,用被減數與上面的結果相加:

1111 1101 + 0100 1111 = 1 0100 1100

把上述結果加一再減去9位二進位制數的最小值1 0000 0000

1 0100 1100 + 1 = 1 0100 1101

1 0100 1101 – 1 0000 0000 = 0100 1101

得到上述結果0100 1101 = (10)77

我們通過相同的方法在二進位製上的使用,求出了同樣的結果77。細心的同學已經可以觀察到,這裡需要用到的減法步驟,其實並不需要真正的減法。例如,第一步,用1111 1111 – 1011 0000得到的結果0100 1111,其實就是對1011 0000的取反,而取反,我們其實只需要通過取反器就可以實現了。然後,在最後一步,我們減去1 0000 0000其實我們要做的就是把溢位的那個1去掉就得到我們的結果。

看完了上面的演示,解釋一下這個實現的方式:

首先用十進位制來解釋一下,我們用999 – 176 + 253 + 1 - 1000這個式子來得到結果。若我們把這個式子根據運算規律簡單地做一些變換:253 + (999 – 176) + 1 – 1000,可以看到,我們其實就是在加上1000後再減去1000。在此我們把用999減去乙個數再加一的這種做法稱為求9的補數。

而對二進位製做同樣的轉換後,即對乙個數先全部為取反,然後再加一,就得到了乙個數的二進位制補數。說到這裡,我們大概也就明白了為什麼我們在計算機中使用補數來表示乙個負數的原因了。因為我們知道,減乙個正數,其實就是加乙個負數。那麼我們就可以想一種方法,讓這個負數的表示既容易表示,用符合運算的規律。顯然,只用符號位不行,僅僅取反也不行。而補數則可以。

我想這大概就是計算機中使用補數來表示負數的原因吧。因為即使是現代的計算機處理器中,其加法器的基本實現的方式都是不變的,只是變得更加高效而已,而為了使用這種加法器的簡單性,我們就使用補碼這種方式來復用加法器來計算減法運算。

二進位制補碼

二進位制補碼 計算機儲存資料都是以0,1二進位制進行儲存。對於有符號整數儲存 對於浮點數待續 引入補碼概念。原碼即直接將真值轉換為其相應的二進位制形式,而反碼和補碼是對原碼進行某種轉換編碼方式。對於正整數,原碼,反碼和補碼都相一樣 對於負整數,補碼等於反碼加1,而反碼等於原碼除符號位不變其他位按位求...

二進位制補碼

計算機只能識別0和1,使用的是二進位制,而在日常生活中人們使用的是十進位制,正如 亞里斯多德早就指出的那樣,今天十進位制的廣泛採用,只不過我們絕大多數人生來具有10個手指頭這個解剖學事實的結果.儘管在歷史上手指計數 5,10進製 的實踐要比二或三進製計數出現的晚.摘自 數學發展史 有空大家可以看看哦...

二進位制補碼

二進位制補碼主要是為了解決負整數的加減法運算 減法轉化為加法 原碼表示法就是用二進位制的最高位表示符號,0表示正數,1表示負數。以8位為例 1就是表示為0000 0001,1表示為1000 0001.而補碼的規則是正整數保持不變,針對負整數,除符號位外,其他位全部取反,然後 1。注 負整數中,原碼轉...