當前位置:首頁 > 公眾號精選 > CPP開發(fā)者
[導(dǎo)讀]在計算機中,所有的數(shù)字都是以二進制的形式表示的,即均為0和1組成的各種編碼,數(shù)字的表示形式可以劃分成原碼,反碼和補碼如何表示原碼、反碼、補碼如果沒有特殊說明,下面的介紹都是以4位二進制為例的原碼為了區(qū)分正數(shù)和負數(shù),計算機中將二進制的最高位(bit)規(guī)定為符號位,它等于0時表示正數(shù)...

在計算機中,所有的數(shù)字都是以二進制的形式表示的,即均為 0 和 1 組成的各種編碼,數(shù)字的表示形式可以劃分成原碼,反碼和補碼


如何表示 原碼、反碼、補碼

如果沒有特殊說明,下面的介紹都是以 4 位二進制為例的


  • 原碼


為了區(qū)分正數(shù)和負數(shù),計算機中將二進制的最高位( bit ) 規(guī)定為符號位,它等于 0 時表示正數(shù),等于 1 時表示負數(shù),剩下的所有低位( bit )用來表示數(shù)值


下面的圖片從左到右分別表示  5和 -5的原碼




  • 反碼


正數(shù)的反碼和其原碼相同,負數(shù)的反碼在原碼基礎(chǔ)上,符號位不變,數(shù)值位取反


下面的圖片從左到右分別表示  5和 -5的反碼




  • 補碼


正數(shù)的補碼和其原碼相同,負數(shù)的補碼在反碼基礎(chǔ)上加1


下面的圖片從左到右分別表示  5和 -5的補碼




為什么用補碼

在計算機中,數(shù)字是以補碼的形式進行存儲和參與運算的


這看起來比較奇怪,為什么要采用補碼這么麻煩的方式表示數(shù)字( 特別是對于負數(shù) ),直觀一點兒不好嗎?


為了講明白這個問題,下面我們分別以原碼,反碼和補碼的形式來模擬二進制的加法和減法運算,以 4 位二進制為例來說明


  • 原碼


下圖列出了 4 位二進制所有正數(shù)和負數(shù)的二進制表示


對于 4 位二進制來說,最高位是符號位,也就是圖中黃色二進制的 0 和 1 的位置




用原碼模擬 3 2、6 (-2) 、(-1) (-3) 運算,具體的運算過程如下:




上圖中,圓圈中的二進制位是做加法運算的時候向前進位的結(jié)果,由于有效二進制位數(shù)是 4 位,所以圓圈中的二進制位因溢出而自動丟棄(在計算過程中仍然用到了溢出的二進制位,結(jié)果會丟棄溢出的二進制)


由計算過程可知,3 2 = 5是正確的,但是 6 (-2) = 0以及 (-1) (-3) = 4結(jié)果都是錯誤的


所以,原碼雖然直觀易懂,也易于轉(zhuǎn)換,但是在運算上,正數(shù)之間的加法是沒問題,負數(shù)之間以及正數(shù)和負數(shù)之間都存在問題,因此計算機中不能用原碼表示數(shù)字


  • 反碼


下面列出了 4 位二進制所有正數(shù)和負數(shù)的二進制表示,請看下圖


正數(shù)的反碼是其自身,負數(shù)的反碼是符號位不變,其他位取反,圖中黃色二進制位表示符號位




用反碼模擬 3 2、6 (-2) 、(-1) (-3) 運算,具體的運算過程如下:




和原碼一樣,上圖中圓圈中的二進制位由于溢出而被自動丟棄,在反碼的運算中,只有 3 2 = 5是正確的,其他的結(jié)果都不正確


注意:(-1) (-3)的結(jié)果是 1010,符號位為 1,表示結(jié)果是負數(shù),根據(jù)上面負數(shù)十進制對應(yīng)二進制的反碼表可知,它對應(yīng)的十進制是 -5


由反碼運算結(jié)果來看,正數(shù)的加法結(jié)果是正確的,負數(shù)和負數(shù)以及正數(shù)和負數(shù)加法的結(jié)果是錯誤的,所以,計算機中也不能用反碼表示數(shù)字


  • 補碼


說完了原碼和反碼,現(xiàn)在來看下補碼,下圖是正數(shù)和負數(shù)補碼的二進制表示




用補碼模擬 3 2、6 (-2) 、(-1) (-3) 運算,具體的運算過程如下:




由上述計算過程可知,除去溢出的二進制位后,3 2、6 (-2)、(-1) (-3)計算的結(jié)果全都正確


用原碼和反碼的表示方式,都不能解決加法運算,但是用補碼表示,不管是正數(shù)之間、負數(shù)之間還是正數(shù)和負數(shù)之間的加法,都可以解決


所以,計算機選擇用補碼來表示數(shù)字以及用補碼進行運算


補碼的好處

  • 簡化減法計算


補碼在加法或減法處理中,不需因為數(shù)字的正負而使用不同的計算方式。只要一種加法電路就可以處理各種有符號數(shù)和無符號數(shù)加法


而且減法可以用一個數(shù)加上另一個數(shù)的補碼來表示,因此只要有加法電路及補碼電路即可完成各種有符號數(shù)和無符號數(shù)加法及減法,在電路設(shè)計上相當方便


  • 統(tǒng)一表示數(shù)字 0


另外,根據(jù)上一小節(jié)中, 0和 -0的補碼都是 0000,對應(yīng)的十進制是 0


也就是說 0的補碼就只有一種表示方式,在計算機中也就有唯一的表示,這和反碼不同(在反碼中,0有二種二進制表示方式),因此在判斷數(shù)字是否為 0 時,只要比較一次即可


由于  0和 -0的補碼只有一種表示方式,即 0000,但是原碼和反碼都有兩種表示方式,所以補碼會多出一種二進制表示方式 1000( 以 4 位二進制為例 ),對應(yīng)十進制數(shù) -8


補碼是怎么來的

前面講到 負數(shù)的補碼是其反碼加 1 , 為什么要這么計算呢, 這么計算就是有效嗎 ?


在十進制中,一個負數(shù)可以通過 0 減去一個正數(shù)得到,同樣的,二進制中也可以


比如:-3可以表示成 0 - 3,也可以表示成下面的二進制減法計算




因為 0 ( 0000 )小于 3 ( 0011 ),根據(jù)算術(shù)運算規(guī)則,當被減數(shù)的位小于減數(shù)時,需向前一位借 1,


0000向前一位借 1后變成了 1 0000,于是,上面的減法計算就變成了




我們知道, 1 0000可以表示成 1111與 1的和, 也即 1 0000 = 1111 1, 于是,計算就變成了




根據(jù)上面的計算,00000) 減 30011) 的結(jié)果是 1101, 而 1101剛好是 -3的補碼


其實,上面的計算過程就相當于先求反碼然后加 1 , 請看下圖




1111 減去 3 的源碼 0011,結(jié)果是 -3 的反碼 1100,然后再加 1 ,得到 -3 的補碼 1101


再看看前面介紹的,負數(shù)的補碼等于其反碼加 1,是不是有點兒似曾相識呢,是的,負數(shù)的反碼就是這么來的,它并不是一個毫無根據(jù)的定義,而是通過上面的計算一步一步得出來的,只不過補碼的計算方式剛好是其反碼加 1 而已


為什么補碼適合正數(shù)的加法

我們還是以 4 位二進制為例來進行說明


假如有兩個正數(shù) A 和 B,現(xiàn)在要證明 A 減 B 的結(jié)果等于 A 加上 B 的補碼


減去一個數(shù)等于加上一個負數(shù),所以 A - B = A ( 0 - B )


由上一小節(jié)可知, ( 0 - B ) 等價于 ( 1111 - B ) 1


所以,A 加 B 的補碼就等于 A ( 1111 - B ) 1,假如結(jié)果為 R ,則有 R = A ( 1111 - B ) 1


A ( 1111 - B ) 1 可以寫成 A - B ( 1111 1 )


A - B ( 1111 1 ) 又可以寫成 A - B 1 0000 ( 1111 1 = 1 0000 )


我們是以 4 位二進制為例的, 1 0000 已經(jīng)超過 4 位了,所以加 1 0000 時,最高位會因溢出而被丟棄


其實這時 1 0000 就相當于 0000 了(最高位溢出,需要丟棄)


所以,上面的計算


R = A   ( 1111 - B )   1
= A - B   ( 1111   1 )
= A - B   1 0000
= A - B     0000
= A - B
這樣就證明了 A 減 B 等于 A 加上 B 的補碼


小結(jié)

本文介紹了原碼、反碼以及補碼,重點闡述了補碼的由來以及證明了補碼計算正數(shù)加法的可行性


- EOF -


本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。

CPP開發(fā)者

234 篇文章

關(guān)注

發(fā)布文章

編輯精選

技術(shù)子站

關(guān)閉