計算機中的數均以0和1組成各種編碼,在計算機中參與運算的數有兩大類: 無符號數和有符號數。
計算機中的數均放在寄存器中,通常稱寄存器的位數為機器字長。
對于有符號數,我們需要使用一位標志位表示其正負符號,這就引出了幾種編碼表示方式。 (下面均以8位機器字長進行分析)
原碼
將最高位用來表示其正負標志:
正數最高位為0
負數最高位為1
例如:
[+1]原 = 0,000 0001
[-1]原 = 1,000 0001
但是這就帶來一個問題,做普通的加法運算的時候:
1+1=0,000 0001 + 0,000 0001 = 0,000 0010 = 2 正確
1-1= 1+(-1)= 0,000 0001 + 1,000 0001 = 1,000 0010 = -2 錯誤
這就意味著在計算減法時,我們不能直接通過原有的加法電路來計算減法,而需要重新設計專門的計算電路來處理原碼表示方法中的符號位的計算。
反碼
反碼可以通過原碼轉換得到:
當值大于0時,反碼和原碼相同
當值小于0時,反碼=保留符號位,其余部分按位取反
例:
[+1]反 = 0,000 0001
[-1]反 = 1,111 1110
對其做加法運算:
1+1=0,000 0001 + 0,000 0001 = 0,000 0010 = 2 正確
1-1= 1+(-1)= 0,000 0001 + 1,111 1110 = 1,111 1111
將其轉換為原碼為1,000 0000 = -0 = 0 正確
補碼
補碼的計算規(guī)則:
當值大于0時,補碼和原碼相同
當值小于0時,補碼=保留符號位,其余部分按位取反,然后+1(即在反碼的基礎上+1)
例:
[+1] = [00000001]原 = [00000001]反 = [00000001]補
[-1] = [10000001]原 = [11111110]反 = [11111111]補
對其做加法運算:
1+1=0,000 0001 + 0,000 0001 = 0,000 0010 = 2 正確
1-1= 1+(-1)= 0,000 0001 + 1,111 1111 = 1 0000 0000
由于最高位溢出,得到0,000 0000=0 正確
從以上我們知道,原碼是最適用于人類認知的一種編碼方式,但是為什么會有反碼和補碼的編碼方式呢?
從上面關于原碼計算減法的計算方案我們知道,由于將符號位直接帶入計算中帶來的影響,在做減法的時候,往往得到的是錯誤的答案。
反碼的提出使直接將符號位帶入計算成為了可能。將減法運算,轉換為加上減數的相反數,使減法計算可以復用加法計算電路。
下面我們來看如下兩個數值:
[0,000 000]反 = +0
[1,111 111]反 = -0
這樣就造成了0有兩種表示方法,使原本8位長度的寄存器只能表示-127-0, 0-127共255個值,比無符號數的表示方法少了一個值,因為0有+0和-0兩個表示方法。
而補碼的出現,解決了0有+0和-0兩種表達方式的困境,我們人為規(guī)定1,000 0000用來表示-128,因為原碼無法表示-128,按正常程序更無法求得其補碼。
這樣一來,我們就只有唯一的[0]補的表現形式0,000 0000,而且多了一個[1,000 0000]補表示負數的最小值-128
通過以上我們看到,計算機通過將有符號數進行不同的進位和表示方法,巧妙地將符號位參與到了加法運算中,那么其中的數學原理是什么呢?
下面首先介紹幾個概念:
同余
兩個整數a,b,若它們除以整數m所得的余數相等,則稱a,b對于模m同余,記作 a ≡ b (mod m),讀作 a 與 b 關于模 m 同余。
例:
4 mod 12 = 4
16 mod 12 = 4
28 mod 12 = 4
所以4, 16, 28關于模 12 同余。
計算機的字長有限,當計算得到的結果大于寄存器所能的最大長度時,會發(fā)生溢出,最高位將被舍去。
例:
對于無符號數,8位寄存器所能表達的最大數字為max = 2^8-1,那么當做加法運算max+1時,由于發(fā)生溢出,最高位被丟棄,得到的結果其實是
(max+1) mod 28,只取到對于28的余數部分。
即計算機中的所有運算實際上都是關于2^字長的同余計算。
補碼的數學證明
任何計數系統(tǒng)都必須有兩個參數:容量和精度。
模是衡量計數系統(tǒng)容量的參數。模代表了計數系統(tǒng)所能表示和存儲的狀態(tài)數。
比如對于字長為8的計算機,其最大能表示0-255的數,所以其模為256=28
任何有限的計數系統(tǒng)都有一個確定的模。如時鐘的模是12,時鐘每經過12小時會重新從1開始計數。
計算機同樣也是一個有限容量的計數系統(tǒng),其模m=2字長。
設m > b >= 0,b為整數
則b的補 b = m – b (這里定義的是補,而不是補碼)
由于有正負數,計算機中對正負數的補碼進行了區(qū)分定義:
1> 正整數b的補碼為自身,即b的補碼仍為b
2> 負整數-b的補碼為b的補,即b
我們知道,a - b即可轉化為 a + (-b),如果用補碼來運算
a – b = [a + (-b) ] (mod m) 在計算機中計算的是 [a + b補 ] (mod m)
如果能證明 [a + (-b) ] (mod m)與[a + b補 ] (mod m)同余,那么就能說明通過以上兩個式子在計算機中都能得到正確的值。
∵ b 補= m – b
∴ a + b補 = a + (m – b) = a - b + m
又 ∵a - b + m 與a - b關于m同余
∴ a - b 和 a + b補關于m同余
∴ 將負數轉化為補碼進行計算后,仍然是成立的
所以,計算機中用補碼來儲存所有的數后,就不需要增加減法器了,用加法器就可以代替計算減法,這樣能節(jié)省電路設計。
.
參考資料:
http://www.cnblogs.com/organic/p/6486676.html
http://blog.csdn.net/vickyway/article/details/48788769
http://baike.baidu.com/item/%E5%90%8C%E4%BD%99%E5%AE%9A%E7%90%86/1212360?fromtitle=%E5%90%8C%E4%BD%99&fromid=1432545
https://zh.wikipedia.org/wiki/%E5%90%8C%E9%A4%98
https://www.zhihu.com/question/20159860/answer/21113783