二進位制補碼運算

2021-10-08 10:40:22 字數 4714 閱讀 2789

二進位制負數的在計算機中採用補碼的方式表示。很多人很好奇為什麼使用補碼,直接使用原碼表示多好,看上去更加直觀和易於計算。然而事實告訴我們,這種直觀只是我們人類的一廂情願罷了,在計算機看來,補碼才是它們最想要的。那麼,為什麼計算機使用補碼更好,又是如何通過補碼來計算數值的呢?

我看過網路上很多解釋補碼的文章,幾乎一致的回答就是符號位不變,其他各位逐位求反再加一。在此我想說,這些都不是根本原理。誰都知道這麼求,數電第一章就明確寫了怎麼求,關鍵是為什麼這麼算,其中的原理是什麼?

1.什麼是補碼

這個沒有找到官方定義,只進行個人定義。   

個人定義:補碼是計算機中用來表示負數,使得負數能夠使用加法器參與加法運算的一種碼。

加減是計算機中最常用的運算,加法一般使用加法器來實現,減法則使用減法器實現。那有什麼辦法可以將減法變為加法,這樣就可以讓系統只實現加法即可,答案就是補碼。

理解補碼最簡單的例子就是時鐘。

例1:假如乙個時鐘現在顯示的是10點鐘,如何將它調到6點鐘?

解:有兩種方法,一是向後撥8個小時,二是向前撥4個小時

在這個例子中,8 和 4 互為補數,也就是說4的補碼是8,8的補碼是4,而這個時鐘的模就是12

注意:可能有人會想,在往後調8個小時雖然也調到了6點,但是他實際上比原來日期多了12小時。是的,的確如此,但是你的時鐘有地方儲存了這多餘的12個小時嗎?答案是沒有,所以在你調完後,你沒有記錄這12個小時,換句話說,你把這溢位的12個小時自動捨棄了。當第二個人來檢視鬧鐘時間的時候,他看到的時間就是準的。

例2:乙個數的數值是11,他的模是16,那麼他的補碼是多少?

解:16-11 = 5,即補碼就是5。

2.模關於模沒有找到固定的定義,簡單來說模就是乙個迴圈的週期,在例1中,時鐘的乙個週期就是12,所以模是12。一周的模是7天,一天的模是24小時。模是補碼的乙個重要概念。

3.使用補碼運算

例3模為32,使用補碼運算該算式16-13,13 - 16。

解 16-13 = (16 + (32-13))% 32 = 35 % 32 = 3 

13-16 = (13 + (32-16))% 32 = 29 % 32 = 29

4.使用補碼進行二進位制運算    

有看過數電基礎的都應該記得,第一章就有說明二進位制補碼是如何運算的。正數的補碼即為自己,負數的補碼為符號位不變,其餘逐位求反再加1。

使用該定義,先通過例子求出數值,再對例子進行詳細講解,為什麼可以使用負數的補碼來運算。

例4   通過二進位制求15-11的值

要想讓減法變加法,必須轉換算式為 15 + (-11)

15為正數,符號位為0,二進位制表示為 01111

-11為負數,符號位為1,負數原碼為  11011 ,補碼符號位不變,其餘逐位求反再 +1,即 10101

所以 15 + (-11) = 01111 + 10101 = 100100 捨棄第一位溢位位,即00100,即+4

這是乙個最簡單的補碼演算法運算的例子,卻有很多不解之處。

1.為什麼負數 (-11 )逐位求反再+1就可以代表原來的數?

2.為什麼第一位捨棄

3.為什麼符號位能夠參與運算

先看問題1,-11 先不考慮符號,觀察11的二進位制表示,11使用二進位制表示是 1011,將1011 逐位求反 得到 0100,因為是逐位求反,1011 +0100 = 1111 ,而1111 + 1 = 10000,發現了什麼?10000是四位2二進位制數的模。為什麼10000是4位二進位制數的模呢?原理也很簡單,4位暫存器最高能表示什麼數?即 (二進位制)1111 = (十進位制) 15 , 15 +1 =16 = (二進位制)10000,後四位暫存器清0,所以模為16。

所以不管幾位二進位制數,取反後得到的值加原碼會剛好的到所有的位都是1的二進位制數,再加一就剛好進製得到模。所以取反加一是無論如何都能取到補碼的。比如 :(原)101 +  (補)((反)010 +1) = 8 ,(原)10 + (補)((反)01 +1)= 4。

所以,負數符號位不變,其餘逐位求反 +1 只是算出補碼最簡單的方法,而不是理論基礎。

前面提到過,使用補碼代替原碼,計算後模掉溢位得到數值就可以得到計算的值了。

再看問題2,為什麼高位捨棄,這個問題其實在例1中已經做了說明,因為你沒有儲存這個高位的空間,用最簡單的解釋來解釋就是,乙個4位的暫存器,只能儲存資料的後四位,第一位進製沒地方放,就像例1中多出來的12小時,沒有地方儲存,那麼就丟棄了,反正結果正確就行。可能有人會問,你說丟棄就丟棄嗎,丟了你怎麼保證是正確的?

重新再看一次例4,現在考慮符號位,將符號位加入運算。

15 - 11 = 15 + (-11),其中 -11 為 11011(加了一位符號位,所以模為 16 * 2^1) 他的補碼為 10101 = 21

所以 15 -11 變為 15 +21 = 36 (01111 + 10101) ,原先是減乙個數,變換後卻變成了乙個比減數更大的加數了,能不溢位嗎。所以要模掉溢位位 36 % 32 = 4 。仔細觀察被模數36 = 1 00100 你會發現,在第二位之前的所有高位都是32的倍數,所以用32進行模運算就會全部清0,這就是為什麼高位可以直接捨棄的原因,因為高位永遠會是模的倍數,在模的過程中會被清0。

最後看問題3,為什麼符號位能夠參與運算,可能在這前面一直被符號位困擾,為什麼參與運算就沒有問題,看了這裡的解釋,我相信你講不會再被困擾。

符號位對於我對二進位制補碼的理解產生了很大的阻礙,我不明白為什麼符號位可以參與運算,而且算出來還是對的。花了不少時間理解了符號位的含義。

首先放棄符號位就是計算機表示專門定義出來表示正數和負數用的這個思維,換成這樣一種理解思路:我們觀察計算機中乙個二進位制數,它沒有專門的符號位,但是正數和負數在計算機中儲存第一位二進位制數會存在差異,如果它的第一位是0,那麼他就是正數原碼,如果它的第一位是1,那麼他就是負數補碼,我們通過觀察第一位是0還是1即可知道這個數是正數還是負數。

通過以下例子,可以發現符號位其實是算出來的。

例5:計算機運算 9 - 12

解:9 轉五位二進位制為 01001 //模為32(100000)

因為12是減數,所以將12轉為補碼變為加數,方便參與加法運算

12 = 01100(原) = 10011 + 1 = 10100(補)

01001 + 10100 = 11101

11101% 100000= 11101

從結果看,我們可以發現,第一位為1,第一位如果是1,那麼這個數值是負數補碼,由此可知,這個數是乙個負數,只是在計算機中,他表示為11101,反求原碼,即可得到 (11101 - 1) 反 = 00011  = 十進位制數 3,由此可知,11101表示的是負數的3

從這個例子當中可以看到,在運算中完全沒有考慮符號位,僅用單純的加法運算進行運算,而得到的結果11101也沒有人為去新增乙個符號位,符號位是計算所得的,所以他才能參與運算。我們應該反過來看符號位,正是在補碼運算中,存在第一位為0則是正數,為1則是負數這個規律,我們才方便地認定第一位為符號位,符號位跟人為定義沒有任何關係(人為定義的符號位不可能滿足數學規則參與數**算)。

補充:在例5中可以發現,我們在第一位之前補了乙個0,將四位二進位制數補成五位二進位制數來計算,為什麼要補這個0呢?為了說明這個問題,我們來算乙個錯誤的運算

例6:計算機運算 0 - 12

解 : 我們僅僅用四位二進位制數(四位暫存器)來算

12 = (二進位制)1100 12轉為二進位制後是乙個四位二進位制數,它的模為10000

因為12是減數,所以將12轉為補碼變為加數,方便參與加法運算

12 = 1100(原) = 0011 + 1 = 0100(補)

0000 + 0100 = 0100 = 4 ,第一位是0,說明是正數原碼, 即運算結果為 +4

4 != -12 運算出錯

通過結果發現,只用四位二進位制數運算,結果是錯誤的,為什麼會產生這種錯誤呢?因為暫存器位數不夠,四位暫存器只能儲存 0 -15 的數值,沒有多餘的暫存器位置用來表示這個數的正負,我們雖然算出了符號位,但是計算後所得到的符號位卻沒有地方存放,導致符號位缺失,我們又誤將四位二進位制數結果的第一位當做符號位來判斷數的正負,才會出現錯誤的結果。

通過例5我們可以知道,符號位是計算後得出來的,所以我們要預先要在暫存器第一位留出乙個位置存放計算後得出的符號位,所以我們先在第一位前面補乙個0佔位。

由此可知: 要想計算結果正確, 需要滿足 : 暫存器位數 >= max(運算元1,運算元2,....) 的二進位制位數加一位

有如下幾點:

1:五位二進位制數的所有正數都在圓環的黑線上,而負數都在圓環的紅線上,如果在黑線上,那麼六位暫存器第一位必為0,而在紅線上,那麼第一位必為1,我們也是通過這個位來判斷數值的正負

2:五位二進位制數運算結果取模後如果在黑線上,那麼為正數,否則為負數

3:嘗試寫幾個數字轉為五位二進位制數或者寫幾個算式對號入座,觀察是否符合,加深理解

到這裡補碼的原理就差不多講清楚了,無非是使用模進行轉化,但是我們站在十進位制的角度,去看二進位制的東西,的確會顯得相當費解。最後我想說,能發明補碼來計算的數學家真的是太厲害了。

內容有相互巢狀成分,閱讀後回顧前面的內容可能會更加深入理解。

還有很多特殊情況沒有考慮,只講解了最核心的內容。

本文純屬個人理解,如有紕漏,請勿拍磚。

**二進位制負數的在計算機中採用補碼的方式表示。很多人很好奇為什麼使用補碼,直接使用原碼表示多好,看上去更加直觀和易於計算。然而事實告訴我們,這種直觀只是我們人類的一廂情願罷了,在計算機看來,補碼才是它們最想要的。那麼,為什麼計算機使用補碼更好,又是如何通過補碼來計算數值的呢?

二進位制 補碼 運算

問乙個基本的問題。負數在計算機中如何表示?舉例來說,8在計算機中表示為二進位制的1000,那麼 8怎麼表示呢?很容易想到,可以將乙個二進位制位 bit 專門規定為符號位,它等於0時就表示正數,等於1時就表示負數。比如,在8位機中,規定每個位元組的最高位為符號位。那麼,8就是00001000,而 8則...

二進位制補碼

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

二進位制補碼

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