計算機中的原碼 反碼 補碼分析

2021-07-24 12:33:19 字數 3163 閱讀 8128

今天給學生上數字邏輯第一節課,主要講了數制,後面簡單提及了原碼、反碼和補碼,碰到了兩個問題:第一,十進位制數轉八進位制數,學生練習時卡殼,不知道無從下手;第二,原本以為原碼、反碼、補碼應該是一年級甚至中學時就應該解決的問題,實際上原來根本不是這麼回事。中學老師即使講過,估計也是對付考試的方式簡單提及,並未從本質上進行講解(那時候他們忙著對付高考,哪有閒工夫講這些題外的知識)。

首先,我們明白計算機中的數都是用二進位制表示的,如3用二進位制表示為:

(3)10 = (11)2

那如果-3呢?

顯然,最直接的辦法是用0或1來表示符號。很自然的,我們可以在數值前加符號位來表示,用0表示正數,用1表示負數。為了描述方便,我們後面統一用8位字長來舉例描述,如:

(3)10 = (00000011)2

(-3)10 = (10000011)2

對於8位二進位制數,原碼的表示範圍是:[(11111111)2, (01111111)2],即[-127, 127].

從直覺上,貌似已經解決了正負數的表示問題。但是,問題來了,第乙個問題是:0的表示不唯一(計算機的準確性和唯一性遭遇挑戰):

0 = (+0)10 = (00000000)2

=(-0)10 = (10000000)2

隨之而來的是第二個問題,如3-5如何處理?如果用二進位制的減法規則

(00000011)2 - (00000101)2 = (11111110)2 (原碼中(11111110)2 = (-126)10)

如果按照3-5=3+(-5),則

(00000011)2 - (10000101)2 = (10001000) 2 = (-8)10

也就是說,不論按照原碼的減法和原碼的加法計算,我們不僅沒有得到正確的結果,而且兩種方式得到的結果還不一致。在計算機中,為了降低電路設計的複雜性,所有的減法都是按照加法來計算的,但是從上面的結果看,這些結果無疑都是錯誤的;並且0有兩種表示方法,這就給計算中帶來了困難,在計算時到底是用+0還是用-0?計算過程中的本質問題是:符號位參與計算,不可避免地會導致計算錯誤,即原碼中的符號位是無法參與計算的。

正確的做法應該是:如果用原碼計算減法操作,我們需要先判斷誰的絕對值大,如果被減數的絕對值大,則計算結果的符號位為0,反之則為1,結果中的數值應該是用絕對值大得減去絕對值小的即為正確結果。如3-5的計算過程應該是:由於3<5,所以結果為負,符號位為1,5-3=2,所以結果為-2。如果是這樣的計算過程,計算機應該設計絕對值比較電路,並且設計減法電路。很顯然,這會極大地增加電路設計的成本,並且增加執行中的功耗。

為了應對原碼計算中的問題,有人發現反碼可以解決一些問題。首先,我們看反碼的定義:

正數的反碼與原碼一樣,負數的反碼為:符號位取1,數值部分按位取反。

如-5可表示為(11111010)2。 這樣,上例中的計算似乎可以順利解決了

3 - 5 = 3 + (-5) = (00000011)2 + (11111010)2 = (11111101) 2 = (-2)10,結果正確,ok了嗎?

那我們再看下面乙個例子:-3 - 5 = -3 + (-5)

-3 + (-5) = (11111100)2 + (11111010)2 = (11110110)2 = -9

其結果顯然是錯誤的,即當符號位存在進製時,其結果不正確。那結果是否可以修正呢?還是看-3 + (-5),我們看其演化過程,如果符號位的進製不丟掉,則結果為:

-3 + (-5) = (11111100)2 - (11111010)2 = (111110110)2

如果此時,我們將符號位進製加到最後一位,這結果變為(11110111)2=-8。也就是說,反碼運算允許符號位參與運算,但是,當符號位存在進製時,我們需要對符號位進行修正,將進製加到計算結果的最後一位,修正得到正確結果。但是,這樣同樣需要設計判斷符號位是否存在的電路?

另外,在反碼中,也沒有解決0=+0=-0的二義性問題。

為此,又有人根據模執行的規律,提出了補碼的規則。首先,我們看補碼的定義是什麼?

正數的補碼與原碼相同,負數的補碼為:符號位取1,數值部分為真值取反,然後再加1,即[y]補=2n+y,這裡y是整數, 2n為模m

如-3=(11111101)2, 0=-0=(11111111+1)2=(00000000)2 = +0,即對於0的問題,補碼將+0和-0統一起來了,解決了關於0的二義性問題。

接著我們看3-5和-3-5兩個計算的問題

3-5=3+(-5)= (00000011)2 + (11111011)2 = (11111110)2 = -2

-3-5=(11111101)2 + (11111011)2 = (11111000)2 = -8

即補碼中的符號位參與運算,完美地解決了原碼中和補碼中存在的問題。那為什麼補碼能正確解決這些問題呢?下面我們給出一般的證明。

要證明補碼為什麼能正確進行加法運算,其實需要證明:[x+y]補 = [x]補 + [y]補

證明:

1)若x > 0, y > 0, 這x+y > 0,且x=[x]補, y = [y]補,所以[x+y]補 = [x]補 + [y]補;

2)若x > 0, y < 0, 則x=[x]補, [y]補=m+y(mod m),所以[x]補 + [y]補=m+x+y,這裡需要討論兩種情況:a)若x+y>=0, 則m可捨掉, [x]補 + [y]補 = m+x+y = [x+y]補;b)若x+y < 0,由補碼定義, [x]補 + [y]補 = m+x+y = [x+y]補

3)若x < 0, y > 0, 同2)

4)若x < 0, y < 0, 則x+y < 0. [x]補 = m + x (mod m), [y]補 = m + y (mod m), [x]補+[y]補= m + x + m + y = m + (m + x + y) = m + [x+y]補 = [x + y]補(mod m)

後面這段證明,感興趣的童鞋要好好體會,這個才是正確理解補碼運算的關鍵。

計算機中原碼 反碼 補碼

首先要明白,在計算機中,數以二進位制的形式存在,其中有無符號數和有符號數 無符號數的,相當於十進位制中的自然數,沒有負數,因此八位無符號數的範圍 00000000 11111111,而有符號數的最高位表示符號,最高位為0表示整數 0000 0001 1 最高位為1表示負數 1000 0001 1 原...

計算機中的原碼 反碼和補碼

計算機中的原碼 反碼和補碼 看到這個標題,很多人有話要說了,切!這個東西每一本計算機基礎知識的書中都有介紹的,你還拿出來show什麼嘛!我的原則是你需要就來看一看,懂就不要去理會,倒也不必諷刺兩句,我相信總有需要它的人。當初我看書是沒看明白的,在網上查了好多資料才有所悟。前幾天跟老婆講原碼 反碼和補...

計算機中的原碼 補碼和反碼

數在計算機中是以二進位制形式表示的。數分為有符號數和無符號數。原碼 反碼 補碼都是有符號定點數的表示方法。乙個有符號定點數的最高位為符號位,0是正,1是副。以下都以8位整數為例,原碼就是這個數本身的二進位制形式。例如0000001 就是 1 1000001 就是 1 正數的反碼和補碼都是和原碼相同。...