我所查看的絕大多數(shù)關(guān)于補(bǔ)碼原理的資料都是從鐘表原理吱殉、模數(shù)運(yùn)算之類的開始講起递礼,讓我覺得很混淆岖圈。所以關(guān)于補(bǔ)碼的理解我打算寫一篇基于自己理解注記鹦牛,從符號(hào)位負(fù)權(quán)開始理解搞糕。
約定:下文講解的例子中,中括號(hào)[...]括起的數(shù)表示二進(jìn)制數(shù)曼追。二進(jìn)制位數(shù)的數(shù)據(jù)位為4位窍仰,符號(hào)位為1位,合起來(lái)共5位礼殊。
數(shù)有正負(fù)之分驹吮,比如10的二進(jìn)制數(shù)是[1010],而-7的二進(jìn)制數(shù)是[-0111]晶伦。然而在機(jī)器中是沒有存儲(chǔ)正負(fù)符號(hào)本身的機(jī)制碟狞,為此,我們必須將正負(fù)符號(hào)映射為{0,1}才行坝辫,比如讓0對(duì)應(yīng)負(fù)數(shù)篷就,讓1對(duì)應(yīng)正數(shù),則-7是[0 0111],10是[1 1010]竭业;又或者是讓0對(duì)應(yīng)正數(shù)智润,讓1對(duì)應(yīng)負(fù)數(shù),則-7是[1 0111]未辆,10是[0 1010]窟绷。
究竟選取哪一種比較好呢?理論上來(lái)說(shuō)兩種方法都可以咐柜,只要與計(jì)算機(jī)達(dá)成協(xié)議兼蜈。然而隨意指定映射方案會(huì)引發(fā)兩個(gè)問題:
- 符號(hào)位上的0、1只是單純指定正負(fù)號(hào)拙友,沒有權(quán)值为狸,它們本身無(wú)法參與運(yùn)算,
- 計(jì)算機(jī)在計(jì)算加減法時(shí)必須先要判斷是正是負(fù)遗契,并且要單獨(dú)設(shè)計(jì)加法器和減法器辐棒,
如果只是這樣,那么未免太無(wú)趣了牍蜂。實(shí)際上漾根,如果我們?yōu)榉?hào)位指定負(fù)權(quán)值,那么讓1對(duì)應(yīng)負(fù)號(hào)鲫竞、0對(duì)應(yīng)正號(hào)就有實(shí)際意義辐怕。為什么這么說(shuō)呢?
在上圖中从绘,符號(hào)位(也就是第5位)是負(fù)權(quán)值寄疏。從第4位到第1位的數(shù)據(jù)位最大也只是15([1111]->8+4+2+1=15),那么如果第5位為1顶考,則整個(gè)權(quán)值為(-16+15=) -1赁还,也就是最大值為-1,最小值為-16([1 0000])驹沿,從而達(dá)到標(biāo)識(shí)負(fù)數(shù)的目的艘策;同理,如果第五位為0渊季,則最大值為15([0 1111])朋蔫,而最小值是0([0 0000]),也就達(dá)到了表示正數(shù)的目的却汉。
通過(guò)上面可以看出驯妄,如果為最高位也就是符號(hào)位賦負(fù)權(quán)值,則:
- 符號(hào)位本身可以標(biāo)記正負(fù)性合砂,并且可以參與運(yùn)算青扔,
- 計(jì)算機(jī)不必判斷正負(fù)性,所有的加減法都可以轉(zhuǎn)換為做加法,
基于這種考量微猖,符號(hào)位為負(fù)權(quán)值的這種碼參與運(yùn)算是很方便的谈息,我們稱就稱之為補(bǔ)碼(當(dāng)然為什么叫補(bǔ)碼后面我嘗試分析);另外凛剥,統(tǒng)一將1代表負(fù)數(shù)侠仇,0代表正數(shù)。
然而犁珠,賦負(fù)權(quán)值之后逻炊,這個(gè)二進(jìn)制數(shù)表達(dá)出來(lái)與通常的二進(jìn)制數(shù)不太一樣,比如犁享,-10的普通二進(jìn)制數(shù)(也就是符號(hào)位不賦權(quán)值余素,稱之為原碼)是[-1010]也就是[1 1010],但是補(bǔ)碼是[1 0110]炊昆,顯然二者不同溺森。
這個(gè)補(bǔ)碼是怎么算的呢?因?yàn)?10<0窑眯,則符號(hào)位為1,設(shè)數(shù)據(jù)位為x医窿,則有-16+x=-10磅甩,得到x=6=[0110],綜合就是[1 0110]姥卢。
顯然卷要,按照這種算法,正數(shù)(包括正零)的補(bǔ)碼就是它們的原碼本身独榴,因?yàn)樨?fù)權(quán)值對(duì)于0而言是不影響的僧叉,下面重點(diǎn)看一下負(fù)數(shù)的情況:
從上圖可以看到,如果將該數(shù)的絕對(duì)值(即x)與補(bǔ)碼相加棺榔,就會(huì)有-16+(16-x)+x=24+1=[10 0000]瓶堕,這是因?yàn)?16-x)+x后得到16,也就是[1 0000]症歇,它會(huì)向補(bǔ)碼的符號(hào)位進(jìn)一位郎笆,這導(dǎo)致符號(hào)位也會(huì)向前進(jìn)一位。然而實(shí)際上這里二進(jìn)制數(shù)只有5位忘晤,所以第六位的1實(shí)際應(yīng)該被丟棄宛蚓,最終結(jié)果應(yīng)該是[0 0000],在這里只是說(shuō)明兩者的關(guān)系设塔。
綜上可做如下描述:若令X=-x凄吏,則|X|=x,設(shè)數(shù)據(jù)位有n位,符號(hào)位1位痕钢,則
X補(bǔ)碼+|X|=X補(bǔ)碼+x=2n+1
從而
X補(bǔ)碼=2n+1-|X|=2n+1-x
這便是負(fù)數(shù)的補(bǔ)碼與原碼的關(guān)系图柏。到這里還未結(jié)束,上面式子只是描述一個(gè)算數(shù)關(guān)系盖喷,但是對(duì)于計(jì)算機(jī)而言爆办,因?yàn)樯鲜揭鲆淮螠p法,所以不能立刻得到給定數(shù)的補(bǔ)碼课梳,這就需要引入反碼機(jī)制來(lái)幫助構(gòu)思距辆。
下面通過(guò)一個(gè)例子來(lái)解說(shuō):
這個(gè)例子中,不難看出-5的原碼和反碼若是認(rèn)為都是無(wú)符號(hào)數(shù)(符號(hào)位認(rèn)為是數(shù)據(jù)位暮刃,給正權(quán))跨算,則相加得到[10 1111]也就是(-5原碼:無(wú)符號(hào)數(shù)表示)+(-5反碼:無(wú)符號(hào)數(shù)表示)=24+1+(24-1)。所以如果對(duì)-5的數(shù)據(jù)位取反(符號(hào)位保持不變)椭懊,那么就會(huì)得到它的反碼诸蚕,也就是:(-5反碼:無(wú)符號(hào)數(shù)表示)=24+1+(24-1)-(-5原碼:無(wú)符號(hào)數(shù)表示)=24+1+(24-1)-(5+24)=24+1-1-5。此時(shí)如果給它兩邊再加一個(gè)1氧猬,就得到(-5原碼:無(wú)符號(hào)數(shù)表示)+1=24+1-5背犯,對(duì)比上面給出的x與之補(bǔ)碼的關(guān)系,不難看出最后得到的結(jié)果是數(shù)位表示的就是補(bǔ)碼盅抚。
所以一般而言漠魏,如果是正數(shù)則補(bǔ)碼使其原碼本身,如果是負(fù)數(shù)妄均,那么補(bǔ)碼就是其反碼再加一柱锹。
當(dāng)然分析到這里仍然未結(jié)束,還可以再次化簡(jiǎn)丰包。計(jì)算機(jī)將原碼轉(zhuǎn)為補(bǔ)碼依據(jù)如下結(jié)論:如果是正數(shù)則補(bǔ)碼就是其原碼禁熏,如果是負(fù)數(shù),則從右往左數(shù)遇到第一個(gè)1開始邑彪,將符號(hào)位的右側(cè)瞧毙、該1的左側(cè)的全部取反,即得到補(bǔ)碼寄症,比如-5=[1 0101]升筏,從右往左第一個(gè)1的左側(cè)、符號(hào)位的右側(cè)是三個(gè)數(shù)位010瘸爽,從而對(duì)其全部取反就得到-5的補(bǔ)碼:[1 1011]您访。
為什么可以這樣做呢?注意到剪决,從右往左遇到第一個(gè)1灵汪,說(shuō)明這個(gè)1的右側(cè)必定全部為0檀训,假定符合[1 xx...xx 100...0]的形式,則其反碼就是[1 x'x'...x'x' 011...1]享言,則加1以后就得到補(bǔ)碼[1 x'x'...x'x' 100...0]峻凫,與原碼作對(duì)比,發(fā)現(xiàn)只有中間部分的xx...xx全部取了反變?yōu)閤'x'...x'x'览露。
這里注意有一個(gè)特殊情況荧琼,就是當(dāng)為-0時(shí),其原碼為[1 0000]差牛,但是其補(bǔ)碼則與+0相同命锄,都為[0 0000]。補(bǔ)碼的一個(gè)好處就是將正負(fù)零統(tǒng)一了起來(lái)偏化。既然[1 0000]不再表示-0的補(bǔ)碼脐恩,那么它就可以被用來(lái)表示-24=-16。即數(shù)據(jù)位為n位侦讨、符號(hào)位為1位的二進(jìn)制數(shù)驶冒,最大值是2n-1,最小值是-2n韵卤。比如當(dāng)是8位是骗污,補(bǔ)碼范圍就是[-128,127]。
下面來(lái)說(shuō)說(shuō)補(bǔ)碼的加減法為什么都能轉(zhuǎn)為加法沈条,這實(shí)際上就是要證明:
- x補(bǔ)碼+y補(bǔ)碼=(x+y)補(bǔ)碼??(mod 2n+1)
- x補(bǔ)碼+(-y)補(bǔ)碼=(x-y)補(bǔ)碼??(mod 2n+1)
即 操作數(shù)的補(bǔ)碼和等于操作數(shù)和的補(bǔ)碼身堡、一個(gè)操作數(shù)的補(bǔ)碼與另一個(gè)操作數(shù)求負(fù)后的補(bǔ)碼的和等于兩操作數(shù)和的補(bǔ)碼。
這里的關(guān)鍵在于若已知 y補(bǔ)碼 如何求得 (-y) 補(bǔ)碼拍鲤。可以證明汞扎,y補(bǔ)碼 + (-y) 補(bǔ)碼=0季稳。即
將y補(bǔ)碼包括符號(hào)位都求反(注意!澈魄!不是求反碼景鼠!反碼要求符號(hào)位不動(dòng),這里要包括符號(hào)位也要變化1陨取铛漓!)然后加1即可得到(-y) 補(bǔ)碼。這是因?yàn)橹挥邪ǚ?hào)位在內(nèi)都取反鲫构,y補(bǔ)碼 + (-y) 補(bǔ)碼=[111...1111]浓恶,只要再加一即可得到0滿足關(guān)系式。