計算機機器數原碼、反碼、補碼、有符號數以及無符號數

學C語言時候,計算機二進制數以及有符號、無符號數的一些問題不是很清楚,剛纔看到一個關於有/無符號數的問題就查了一下,現在清楚很多了。

 

這篇文章寫得實在太好了,清楚明白容易理解,就不自己表達,貼過來好了。

 

負數在計算機中如何表示呢?

 

這一點,你可能聽過兩種不同的回答。

一種是教科書,它會告訴你:計算機用“補碼”表示負數。可是有關“補碼”的概念一說就得一節課,這一些我們需要在第6章中用一章的篇幅講2進制的一切。再者,用“補碼”表示負數,其實一種公式,公式的作用在於告訴你,想得問題的答案,應該如何計算。卻並沒有告訴你爲什麼用這個公式就可以和答案?

另一種是一些程序員告訴你的:用二進制數的最高位表示符號,最高位是0,表示正數,最高位是1,表示負數。這種說法本身沒錯,可是如果沒有下文,那麼它就是錯的。至少它不能解釋,爲什麼字符類型的-1用二進制表示是“1111 1111”(16進製爲FF);而不是我們更能理解的“1000 0001”。(爲什麼說後者更好理解呢?因爲既然說最高位是1時表示負數,那1000 0001不是正好是-1嗎?)。

讓我們從頭說起。

1、你自已決定是否需要有正負。

就像我們必須決定某個量使用整數還是實數,使用多大的範圍數一樣,我們必須自已決定某個量是否需要正負。如果這個量不會有負值,那麼我們可以定它爲帶正負的類型。

在計算機中,可以區分正負的類型,稱爲有符類型,無正負的類型(只有正值),稱爲無符類型。

數值類型分爲整型或實型,其中整型又分爲無符類型或有符類型,而實型則只有符類型。

字符類型也分爲有符和無符類型。

比如有兩個量,年齡和庫存,我們可以定前者爲無符的字符類型,後者定爲有符的整數類型。

2、使用二制數中的最高位表示正負。

首先得知道最高位是哪一位?1個字節的類型,如字符類型,最高位是第7位,2個字節的數,最高位是第15位,4個字節的數,最高位是第31位。不同長度的數值類型,其最高位也就不同,但總是最左邊的那位(如下示意)。字符類型固定是1個字節,所以最高位總是第7位。

(紅色爲最高位)

單字節數: 1111 1111

雙字節數: 1111 1111 1111 1111

四字節數: 1111 1111 1111 1111 1111 1111 1111 1111

 

當我們指定一個數量是無符號類型時,那麼其最高位的1或0,和其它位一樣,用來表示該數的大小。

當我們指定一個數量是無符號類型時,此時,最高數稱爲“符號位”。爲1時,表示該數爲負值,爲0時表示爲正值。

 

3、無符號數和有符號數的範圍區別。

無符號數中,所有的位都用於直接表示該值的大小。有符號數中最高位用於表示正負,所以,當爲正值時,該數的最大值就會變小。我們舉一個字節的數值對比:

無符號數: 1111 1111   值:255 1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20

有符號數: 0111 1111   值:127         1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20

 

同樣是一個字節,無符號數的最大值是255,而有符號數的最大值是127。原因是有符號數中的最高位被挪去表示符號了。並且,我們知道,最高位的權值也是最高的(對於1字節數來說是2的7次方=128),所以僅僅少於一位,最大值一下子減半。

不過,有符號數的長處是它可以表示負數。因此,雖然它的在最大值縮水了,卻在負值的方向出現了伸展。我們仍一個字節的數值對比:

無符號數:                       0 ----------------- 255

有符號數:        -128 --------- 0 ---------- 127

 

同樣是一個字節,無符號的最小值是 0 ,而有符號數的最小值是-128。所以二者能表達的不同的數值的個數都一樣是256個。只不過前者表達的是0到255這256個數,後者表達的是-128到+127這256個數。

一個有符號的數據類型的最小值是如何計算出來的呢?

有符號的數據類型的最大值的計算方法完全和無符號一樣,只不過它少了一個最高位(見第3點)。但在負值範圍內,數值的計算方法不能直接使用1* 26 + 1* 25 的公式進行轉換。在計算機中,負數除爲最高位爲1以外,還採用補碼形式進行表達。所以在計算其值前,需要對補碼進行還原。這些內容我們將在第六章中的二進制知識中統一學習。

這裏,先直觀地看一眼補碼的形式:

以我們原有的數學經驗,在10進制中:1 表示正1,而加上負號:-1 表示和1相對的負值。

那麼,我們會很容易認爲在2進制中(1個字節): 0000 0001 表示正1,則高位爲1後:1000 0001應該表示-1。

然而,事實上計算機中的規定有些相反,請看下錶:

 

二進制值(1字節) 十進制值
1000 0000 -128
1000 0001 -127
1000 0010 -126
1000 0011 -125
... ...
1111 1110 -2
1111 1111 -1

 

首先我們看到,從-1到-128,其二進制的最高位都是1(表中標爲紅色),正如我們前面的學。

然後我們有些奇怪地發現,1000 0000 並沒有拿來表示 -0;而1000 0001也不是拿來直觀地表示-1。事實上,-1 用1111 1111來表示。

怎麼理解這個問題呢?先得問一句是-1大還是-128大?

當然是 -1 大。-1是最大的負整數。以此對應,計算機中無論是字符類型,或者是整數類型,也無論這個整數是幾個字節。它都用全1來表示 -1。比如一個字節的數值中:1111 1111表示-1,那麼,1111 1111 - 1 是什麼呢?和現實中的計算結果完全一致。1111 1111 - 1 = 1111 1110,而1111 1110就是-2。這樣一直減下去,當減到只剩最高位用於表示符號的1以外,其它低位全爲0時,就是最小的負值了,在一字節中,最小的負值是1000 0000,也就是-128。

我們以-1爲例,來看看不同字節數的整數中,如何表達-1這個數:

字節數 二進制值 十進制值
單字節數 1111 1111 -1
雙字節數 1111 1111 1111 1111 -1
四字節數 1111 1111 1111 1111 1111 1111 1111 1111 -1

 

可能有同學這時會混了:爲什麼 1111 1111 有時表示255,有時又表示-1?所以我再強調一下本節前面所說的第2點:你自已決定一個數是有符號還是無符號的。寫程序時,指定一個量是有符號的,那麼當這個量的二進制各位上都是1時,它表示的數就是-1;相反,如果事選聲明這個量是無符號的,此時它表示的就是該量允許的最大值,對於一個字節的數來說,最大值就是255。

 

 原碼、反碼、補碼

我們已經知道計算機中,所有數據最終都是使用二進制數表達。

我們也已經學會如何將一個10進制數如何轉換爲二進制數。

不過,我們仍然沒有學習一個負數如何用二進制表達。

 

比如,假設有一 int 類型的數,值爲5,那麼,我們知道它在計算機中表示爲:

00000000 00000000 00000000 00000101

5轉換成二制是101,不過int類型的數佔用4字節(32位),所以前面填了一堆0。

現在想知道,-5在計算機中如何表示?

 

在計算機中,負數以其正值的補碼形式表達。

什麼叫補碼呢?這得從原碼,反碼說起。

 

原碼:一個整數,按照絕對值大小轉換成的二進制數,稱爲原碼。

比如 00000000 00000000 00000000 00000101 是 5的 原碼。

 

反碼:將二進制數按位取反,所得的新二進制數稱爲原二進制數的反碼。

取反操作指:原爲1,得0;原爲0,得1。(1變0; 0變1)

比如:將00000000 00000000 00000000 00000101每一位取反,得11111111 11111111 11111111 11111010。

稱:11111111 11111111 11111111 11111010 是 00000000 00000000 00000000 00000101 的反碼。

反碼是相互的,所以也可稱:

11111111 11111111 11111111 11111010 和 00000000 00000000 00000000 00000101 互爲反碼。

 

補碼:反碼加1稱爲補碼。

也就是說,要得到一個數的補碼,先得到反碼,然後將反碼加上1,所得數稱爲補碼。

比如:00000000 00000000 00000000 00000101 的反碼是:11111111 11111111 11111111 11111010。

那麼,補碼爲:

11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011

 

所以,-5 在計算機中表達爲:11111111 11111111 11111111 11111011。轉換爲十六進制:0xFFFFFFFB。

 

再舉一例,我們來看整數-1在計算機中如何表示。

假設這也是一個int類型,那麼:

 

1、先取1的原碼:00000000 00000000 00000000 00000001

2、得反碼:     11111111 11111111 11111111 11111110

3、得補碼:     11111111 11111111 11111111 11111111

 

可見,-1在計算機裏用二進制表達就是全1。16進製爲:0xFFFFFF。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章