深刻理解計算機系統:定點數的表示和運算

最近學習計算機組成原理時,結合視頻和我的理解作的一些筆記。可能文中有錯誤或者描述不恰當的地方,歡迎評論區指出。git

1.定點數的表示

1.1 無符號數

  • 定義:無符號數就是沒有體現正負號的數(這意味着全部的無符號數實際上都是正數),整個機器字長的所有二進制位均爲數值位,沒有符號位。以108D爲例,它對應的二進制數是 1101100,這實際上也就是它的無符號數,能夠看到全部的位都是數值位。
  • 表示範圍:以八位二進制數爲準,範圍就是 0000000011111111,也就是 0 到 255

1.2 有符號數

  • 定義:有符號數就是有體現正負號的數,整個機器字長的所有二進制位中,最高位做爲符號位,0 表示正數,1 表示負數,其他位則是數值位。依然以108D爲例,它對應的二進制數是 1101100,而對應的有符號數則要在最前面加上符號位 0,即它的有符號數是 01101100.github

  • 表示範圍:以八位二進制數爲準,範圍應該是從負數到正數,即從 1111111101111111,也就是 -127 到 127ide

1.2.1.真值和機器數

  • 真值:就是帶有正負號的實際十進制數,好比上面例子中,+108D就是真值
  • 機器數:機器數就是一個數在計算機中的二進制表示形式,注意機器數是由符號位和數值位構成的,好比上面例子中,01101100 就是機器數。

-156D(真值)= 110011100B(機器數)學習

1.2.2.原碼、反碼、補碼和移碼

(1)原碼錶示法

簡單點理解,原碼就是符號位加上真值(二進制)的絕對值,同時用逗號將符號位和數值位隔開。好比,+1 就是 0,0000001,-1 就是 1,00000013d

原碼的特色是簡單、直觀,可是原碼在進行加法運算的時候會出現問題。正數加正數或者負數加負數是正常的,可是正數加負數就會出錯。好比咱們如今想要計算 -1+3,咱們心想:-1 是 10000001,+3 是 00000011,加起來獲得的是 10000100,因此結果是 -4,但 -1+3 應該是等於 2,因此這個結果是錯的。咱們發現,原本應該作的是加法運算,但實際上變成了減法運算(-1-3=-4)。code

咱們首先想到,能夠經過將「正數加負數」轉化爲「正數減正數」來手動糾正這個錯誤。上面的例子就變成 0000001100000001,結果是 00000010,也就是 2,這個結果是正確的。視頻

可是每次都這樣手動轉化,計算起來仍是太麻煩了。因而咱們接着想:有沒有一種方法,可讓「正數加負數」中的負數等價於一個正數,從而確保始終進行的是相加操做呢?blog

因而這時候就引出了補碼的概念。get

(2)補碼錶示法

  • 補數和模:理解補碼以前,咱們先來理解兩個概念:補數。 拿時鐘舉例,想要從10點撥到8點,有兩種作法,一種是逆時針撥2個單位,記做-2;一種是順時針撥10個單位,記做+10,這兩種操做是等效的(有點負數等價於一個正數的意思)。這時候咱們就說,-2 是 +10 以 12 爲模的補數,記做-2≡+10(mod 12),同理,-5 至關於 +7,-4 至關於 +8。it

  • 那麼怎麼基於補數和模的概念將「正數加負數」轉化爲「正數加正數」 —— 即怎麼令負數等價於一個正數呢?假設咱們如今有一個寄存器能夠存放四位二進制數(此時,模爲16),咱們想要讓 1011 變成 0000,最容易想到的辦法就是 1011-1011=0000,注意這裏是正數加負數。想要變成正數加正數,就要找到等價於 -1011 的正數,-1011 就是 -11,-11 以 16 爲模的補數就是 +5,+5 就是 +0101,這個正是咱們要找的那個等價正數,所以這時候,1011-1011 變成了 1011+0101,其結果是 10000,不要忘了寄存器只能存放四位,因此結果實際上是 0000,剛好與咱們「正數加負數」時獲得的結果無異。

  • 接着引入補碼的概念:

    • 對於正數:正數的補碼和原碼相同;
    • 對於負數:負數的補碼等於其原碼在保持符號位不變的狀況下,其他各位取反,末位加一(取反加一)。注意,補碼的補碼等於原碼,這能夠用來根據補碼求原碼。
    • 也能夠用下圖方法計算補碼:

仍是上面的例子,1011-1011,也就是11-11,咱們考慮+11和-11,+11的原碼=補碼=01011,-11的原碼是11011,所以補碼是10101,那麼01011+10101就會等於100000,由於寄存器是五位的,把前面的1去掉,那麼結果就是00000,也就是0,和上面的運算結果一致。

(3)反碼錶示法

反碼很好理解:

  • 正數:反碼等於原碼等於補碼;
  • 負數:反碼等於原碼保持符號位不變的狀況下其他各位取反。也就是說,補碼=反碼+1
  • 反碼的反碼等於原碼,這能夠用來根據反碼求原碼。

(4)移碼錶示法

補碼存在的問題是,僅從補碼自己來看,很難比較兩個數的大小,爲此引入了移碼的概念。移碼指的是在真值(二進制)的基礎上加上一個偏移量,一般這個偏移量是2^n。其中,n是數值位的位數。例如,對於-10101,其移碼是2^7+(-10101)=10000000+(010101)=0,1101011。 固然,咱們有簡單的方法能夠計算一個數的移碼:無論正數仍是負數,其移碼都等於補碼的符號位取反。

2.定點數的加減運算

2.1 補碼的加減運算

定點數的加減運算實際上就是補碼的加減運算。咱們來看一個例子:

假設機器字長爲 8 位(含1位符號位),A=15,B=-24,如今求 A+B 和 A-B。

A 的補碼是 0,0001111,B 的補碼是 1,1101000,那麼 0,0001111+1,1101000=1,1110111,轉化爲原碼,再轉化爲真值,獲得 -9,這是正確的。同理,A-B 就是 A+(-B),-B 的補碼是 0,0011000,那麼 0,0001111+0,0011000=0,0100111,最後轉化爲真值,獲得 +39,這也是正確的。 咱們再來看另外一個例子:

假設機器字長爲 8 位(含1位符號位),A=15,B=-24,C=124,如今求 A+C 和 B-C。

咱們一樣按照上面的流程來進行計算,最後得出:A+C 結果是 -117,B-C 結果是 +108,這兩個都是錯誤的。爲何會出現這樣的狀況呢?

2.2 溢出

這種狀況就叫溢出。出現的緣由,簡單來講就是:運算結果太大了,或者運算結果過小了。就上面的題而言,8 位二進制數所能表示的數字的範圍是有限的,當正數加正數的時候,結果可能過大,超出了最大值,此時稱爲上溢;當負數加負數的時候,結果可能太小,夠不到最小值,此時稱爲下溢。以下圖所示:

咱們拿 3 位二進制數來理解這個問題。假設 3 位二進制數能夠表示的範圍以下:

如今咱們進行 2+2 操做,那麼就是 010+010,結果就是 100,這已經超出了正數能夠表示的最大範圍,也就是發生了上溢。因此此時獲得的是 -4,這是一個錯誤的結果。

2.3 溢出的判斷

前面說過,溢出的緣由要麼是運算結果太大,要麼是運算結果過小,其實從這句話咱們能夠看出,正數和負數相加是不會發生溢出的,由於其結果必然在能夠表示的範圍內,惟一可能會發生溢出的狀況,要麼是正數加正數,要麼是負數加負數。那麼,如何判斷在這兩種狀況下是否會發生溢出呢?有三個方法:

(1) 一位符號位:比較操做數符號位與結果數符號位

咱們仍是拿上面的第二個例子解釋:

能夠看到,A+C 中,兩個操做數符號位都是 0,也就是都是正數,但結果數的符號位倒是 1 ,也就是負數,那麼很明顯它發生了上溢;

同理,B-C 中,兩個操做數符號位都是 1,也就是都是負數,但結果數的符號位倒是 0,也就是正數,那麼很明顯它發生了下溢。

(2) 一位符號位:看符號位與最高數值位的進位狀況

看第一個式子,進行運算的時候,符號位沒有產生進位,可是最高數值位向前產生了進位,這時候判斷它發生了上溢; 看第二個式子,進行運算的時候,最高數值位沒有產生進位,可是符號位向前產生了進位,這時候判斷它發生了下溢。

(3) 兩位符號位:

這種方法是將一位符號位改成兩位符號位表示:正數符號爲 00,負數符號爲 11。那麼前面的例子就會變爲:

這時候,計算機只須要看結果數就能知道是否發生溢出 —— 只要結果數的兩位符號位相異,那麼就必定是發生了溢出。 同理,咱們回過頭看第一個沒有溢出的例子:

能夠發現兩次運算的結果數的兩位符號位都是同樣的,由此判斷這兩次運算都沒有發生溢出。

參考: www.bilibili.com/video/av669…

相關文章
相關標籤/搜索