1. 程式人生 > >C語言——原碼、反碼、補碼、資料型別取值範圍

C語言——原碼、反碼、補碼、資料型別取值範圍

記得剛學C語言的時候,對應資料型別的取值範圍經常會有這樣的疑問:比如8位的二進位制補碼範圍為什麼是-128~127呀?為 什麼會差一個數呀?(以8位為例)

為了解釋這個問題,我們先來了解下幾個概念(原碼、反碼、補碼):

原碼:它是一種計算機中對數字的二進位制定點表示方法。原碼錶示法在數值前面增加了一位符號位(即最高位為符號位):正數該位為0,負數該位為1(0有兩種表示:+0和-0),其餘位表示數值的大小。它的優點就是簡單直觀,缺點就是不能直接參加運算,可能會出錯。例如數學上,1+(-1)=0,而在二進位制00000001+10000001=10000010,換算成二進位制為-2。顯然出錯了。這也是為什麼計算機儲存方式不能用原碼錶示的原因。

反碼:正數的反碼與其原碼相同;負數的反碼是對其原碼逐位取反,但符號位除外。反碼是數值儲存的一種,但是由於補碼更能有效表現數字在計算機中的形式,所以多數計算機都不採用反碼錶示數。

補碼:正數的補碼與其原碼相同;負數的補碼是在其反碼的末位加1。在計算機系統中,數值一律用補碼來表示和儲存。原因在於,使用補碼,可以將符號位和數值域統一處理;同時,加法和減法也可以統一處理。此外,補碼與原碼相互轉換,其運算過程是相同的,不需要額外的硬體電路。

由上面我們可以知道,在計算機系統中,數值一律是用補碼來表示和儲存的。現在我們來解釋下,為什麼8位的二進位制補碼範圍是-128~127。

在原碼的情況下,8

位可表示的數值範圍為(-127 ~ -0 +0 ~ +127 ),共256個。在這其中 -0 與 +0 其值是一樣的,但是0帶符號是沒有任何意義的. 而且會有[0000 0000]和[1000 0000]兩個編碼表示0,補碼的情況就可以解決這個問題。

1-1 = 1 + (-1) = [0000 0001] + [1000 0001] = [0000 0001] + [1111 1111] = [0000 0000]=[0000 0000]

這樣0用[0000 0000]表示, 而以前出現問題的-0則不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001] + [1111 1111] = [1111 1111] + [1000 0001] = [1000 0000]

-1-127的結果應該是-128, 在用補碼運算的結果中, [1000 0000]

 就是-128. 但是注意因為實際上是使用以前的-0的補碼來表示-128, 所以-128並沒有原碼和反碼錶示.(對-128的補碼錶示[1000 0000]補算出來的原碼是[0000 0000], 這是不正確的)

使用補碼, 不僅僅修復了0的符號以及存在兩個編碼的問題, 而且還能夠多表示一個最低數. 這就是為什麼8位二進位制, 使用原碼或反碼錶示的範圍為[-127, +127], 而使用補碼錶示的範圍為[-128, 127],(可以說用[1000 000]來表示-128 的補碼,這也是人為的一種規定吧)。

總結如下:

1、負數補碼形式從10000001到11111111依次表示-127到-1。

2、用補碼錶示負數時:負數X用2^n - |X|來表示,其中n為機器的字長(模運算)

(關於補碼更詳細的解釋,以及模運算http://baike.baidu.com/link?url=S6y7Pupzmg6PO_vXo3JcWdTRtUriU82AI_tYVYLyaTX5MRMY98A1izQKdqUkD3ym1PV0XcrQYQGKbWLKYXOfwa#3)

當n = 8 時,[-1]補 = 2^8 - 1 = 1111 1111, [-127]補 = 2^8 - 127 = 1000 0001

[-0]補=2^8 - 0 = 00000000 在補碼錶示法中只有一種表示,即 0000 0000 ,跟 +0 一樣

3、[-128]補 = 1 0000 0000 - 1000 000 = 1000 0000

全部補碼形式:

-128 ~ -1 1000 0000 1000 0001 1000 0002 。。。。。。 1111 1111 共128個

0 ~ 127 0000 0000 0000 0001 0000 0002 。。。。。。 0111 1111共128個

恰好是256個編碼!!