計(jì)算機(jī)中的數(shù)均以0和1組成各種編碼辜御,在計(jì)算機(jī)中參與運(yùn)算的數(shù)有兩大類: 無符號數(shù)和有符號數(shù)积锅。
計(jì)算機(jī)中的數(shù)均放在寄存器中灭美,通常稱寄存器的位數(shù)為機(jī)器字長推溃。
對于有符號數(shù),我們需要使用一位標(biāo)志位表示其正負(fù)符號届腐,這就引出了幾種編碼表示方式铁坎。 (下面均以8位機(jī)器字長進(jìn)行分析)
原碼
將最高位用來表示其正負(fù)標(biāo)志:
正數(shù)最高位為0
負(fù)數(shù)最高位為1
例如:
[+1]原 = 0,000 0001
[-1]原 = 1,000 0001
但是這就帶來一個問題,做普通的加法運(yùn)算的時候:
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 錯誤
這就意味著在計(jì)算減法時犁苏,我們不能直接通過原有的加法電路來計(jì)算減法硬萍,而需要重新設(shè)計(jì)專門的計(jì)算電路來處理原碼表示方法中的符號位的計(jì)算。
反碼
反碼可以通過原碼轉(zhuǎn)換得到:
當(dāng)值大于0時围详,反碼和原碼相同
當(dāng)值小于0時朴乖,反碼=保留符號位,其余部分按位取反
例:
[+1]反 = 0,000 0001
[-1]反 = 1,111 1110
對其做加法運(yùn)算:
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
將其轉(zhuǎn)換為原碼為1,000 0000 = -0 = 0 正確
補(bǔ)碼
補(bǔ)碼的計(jì)算規(guī)則:
當(dāng)值大于0時助赞,補(bǔ)碼和原碼相同
當(dāng)值小于0時买羞,補(bǔ)碼=保留符號位,其余部分按位取反雹食,然后+1(即在反碼的基礎(chǔ)上+1)
例:
[+1] = [00000001]原 = [00000001]反 = [00000001]補(bǔ)
[-1] = [10000001]原 = [11111110]反 = [11111111]補(bǔ)
對其做加法運(yùn)算:
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 正確
從以上我們知道,原碼是最適用于人類認(rèn)知的一種編碼方式婉徘,但是為什么會有反碼和補(bǔ)碼的編碼方式呢漠嵌?
從上面關(guān)于原碼計(jì)算減法的計(jì)算方案我們知道,由于將符號位直接帶入計(jì)算中帶來的影響盖呼,在做減法的時候,往往得到的是錯誤的答案化撕。
反碼的提出使直接將符號位帶入計(jì)算成為了可能几晤。將減法運(yùn)算,轉(zhuǎn)換為加上減數(shù)的相反數(shù)植阴,使減法計(jì)算可以復(fù)用加法計(jì)算電路蟹瘾。
下面我們來看如下兩個數(shù)值:
[0,000 000]反 = +0
[1,111 111]反 = -0
這樣就造成了0有兩種表示方法,使原本8位長度的寄存器只能表示-127-0, 0-127共255個值掠手,比無符號數(shù)的表示方法少了一個值憾朴,因?yàn)?有+0和-0兩個表示方法。
而補(bǔ)碼的出現(xiàn)喷鸽,解決了0有+0和-0兩種表達(dá)方式的困境众雷,我們?nèi)藶橐?guī)定1,000 0000用來表示-128,因?yàn)樵a無法表示-128,按正常程序更無法求得其補(bǔ)碼砾省。
這樣一來鸡岗,我們就只有唯一的[0]補(bǔ)的表現(xiàn)形式0,000 0000,而且多了一個[1,000 0000]補(bǔ)表示負(fù)數(shù)的最小值-128
通過以上我們看到编兄,計(jì)算機(jī)通過將有符號數(shù)進(jìn)行不同的進(jìn)位和表示方法轩性,巧妙地將符號位參與到了加法運(yùn)算中,那么其中的數(shù)學(xué)原理是什么呢狠鸳?
下面首先介紹幾個概念:
同余
兩個整數(shù)a揣苏,b,若它們除以整數(shù)m所得的余數(shù)相等件舵,則稱a舒岸,b對于模m同余,記作 a ≡ b (mod m)芦圾,讀作 a 與 b 關(guān)于模 m 同余蛾派。
例:
4 mod 12 = 4
16 mod 12 = 4
28 mod 12 = 4
所以4, 16, 28關(guān)于模 12 同余。
計(jì)算機(jī)的字長有限个少,當(dāng)計(jì)算得到的結(jié)果大于寄存器所能的最大長度時洪乍,會發(fā)生溢出,最高位將被舍去夜焦。
例:
對于無符號數(shù)壳澳,8位寄存器所能表達(dá)的最大數(shù)字為max = 2^8-1,那么當(dāng)做加法運(yùn)算max+1時茫经,由于發(fā)生溢出巷波,最高位被丟棄,得到的結(jié)果其實(shí)是
(max+1) mod 28卸伞,只取到對于28的余數(shù)部分抹镊。
即計(jì)算機(jī)中的所有運(yùn)算實(shí)際上都是關(guān)于2^字長的同余計(jì)算。
補(bǔ)碼的數(shù)學(xué)證明
任何計(jì)數(shù)系統(tǒng)都必須有兩個參數(shù):容量和精度荤傲。
模是衡量計(jì)數(shù)系統(tǒng)容量的參數(shù)垮耳。模代表了計(jì)數(shù)系統(tǒng)所能表示和存儲的狀態(tài)數(shù)。
比如對于字長為8的計(jì)算機(jī)遂黍,其最大能表示0-255的數(shù)终佛,所以其模為256=28
任何有限的計(jì)數(shù)系統(tǒng)都有一個確定的模。如時鐘的模是12雾家,時鐘每經(jīng)過12小時會重新從1開始計(jì)數(shù)铃彰。
計(jì)算機(jī)同樣也是一個有限容量的計(jì)數(shù)系統(tǒng),其模m=2字長芯咧。
設(shè)m > b >= 0牙捉,b為整數(shù)
則b的補(bǔ) b = m – b (這里定義的是補(bǔ)竹揍,而不是補(bǔ)碼)
由于有正負(fù)數(shù),計(jì)算機(jī)中對正負(fù)數(shù)的補(bǔ)碼進(jìn)行了區(qū)分定義:
1> 正整數(shù)b的補(bǔ)碼為自身鹃共,即b的補(bǔ)碼仍為b
2> 負(fù)整數(shù)-b的補(bǔ)碼為b的補(bǔ)鬼佣,即b
我們知道,a - b即可轉(zhuǎn)化為 a + (-b)霜浴,如果用補(bǔ)碼來運(yùn)算
a – b = [a + (-b) ] (mod m) 在計(jì)算機(jī)中計(jì)算的是 [a + b補(bǔ) ] (mod m)
如果能證明 [a + (-b) ] (mod m)與[a + b補(bǔ) ] (mod m)同余晶衷,那么就能說明通過以上兩個式子在計(jì)算機(jī)中都能得到正確的值。
∵ b 補(bǔ)= m – b
∴ a + b補(bǔ) = a + (m – b) = a - b + m
又 ∵a - b + m 與a - b關(guān)于m同余
∴ a - b 和 a + b補(bǔ)關(guān)于m同余
∴ 將負(fù)數(shù)轉(zhuǎn)化為補(bǔ)碼進(jìn)行計(jì)算后阴孟,仍然是成立的
所以晌纫,計(jì)算機(jī)中用補(bǔ)碼來儲存所有的數(shù)后,就不需要增加減法器了永丝,用加法器就可以代替計(jì)算減法锹漱,這樣能節(jié)省電路設(shè)計(jì)。
.
參考資料:
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