二進(jìn)制的原碼、反碼、補(bǔ)碼、移碼

之前了解一些原碼、反碼、補(bǔ)碼,但是一直有疑問,為什么會有原碼、反碼、補(bǔ)碼?所以決定研究一下。

計算機(jī)中參與運(yùn)算的數(shù)有兩大類:無符號數(shù)和有符號數(shù)。此篇主要看一下有符號數(shù)。在了解原碼、反碼、補(bǔ)碼前需要先了解機(jī)器數(shù)和真值。

一、機(jī)器數(shù)

對于有符號數(shù)而言,使用“0”表示正,“1”表示負(fù),這種把符號“數(shù)字化”的數(shù)稱為機(jī)器數(shù),也就是一個數(shù)在計算機(jī)中的二進(jìn)制表示。

例如:+1100 在機(jī)器中表示為 0 1100;-1100 在機(jī)器中表示為1 1100

整數(shù)的符號位和值用逗號隔開,小數(shù)的小數(shù)點用點來隔開。
例如:+3轉(zhuǎn)換成二進(jìn)制就是00000011,-3就是10000011,這就是機(jī)器數(shù)。

二、真值

帶符號位的機(jī)器數(shù)對應(yīng)的真正數(shù)值就是真值。例如:1000 0011的真值是-3,而不是131,它的最高位是符號位。


下面開始說原碼、反碼、補(bǔ)碼。

計算機(jī)里存儲的實際都是數(shù)的補(bǔ)碼,顯示的時候轉(zhuǎn)換為源碼。原碼和反碼都有一定的缺陷。原碼雖然表示簡單明了,并易于和真值轉(zhuǎn)換,但是在加減法運(yùn)算時會有很多麻煩,運(yùn)算步驟復(fù)雜費(fèi)時,還需要計算機(jī)提供減法器來支持。而補(bǔ)碼卻能夠滿足這些要求,計算機(jī)只需要加法器就可以。

三、原碼

原碼是機(jī)器數(shù)中最簡單的一種表示形式,包括符號位和數(shù)值位。

原碼:符號位加上真值的絕對值,即第一位表示符號位,其余為表示值。原碼是人腦最容易理解和計算的表示方式。

[+1]原 = 0000 0001
[-1]原 = 1000 0001

整數(shù)原碼的定義:


式中,x為真值,n為整數(shù)的位數(shù)(位數(shù)不包括符號位,下同)。
例如:
當(dāng)x=1110時,[x]原=0,1110;
當(dāng)x=-1110時,[x]=24-(-1110)=1 1110,2 的4次方就相當(dāng)于是符號位。

計算過程解釋:
對于x的取值范圍(例中的4位二進(jìn)制來說):
2^n的值為:2^4=16
最大值為:1111 = 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0 =8+4+2+1=15
最小值為:0000=0

當(dāng)x為負(fù)數(shù)時,計算過程如下:
[x]原=2^4 - (-1110) = 2^4 + 1110 = 1 0000 + 1110 = 1 1110

小數(shù)原碼的定義為:


式中,x為真值。
例如:
當(dāng)x=0.1101時,[x]=0.1101;
當(dāng)x=-0.1101時,[x]=1-(-0.1101)=1.1101;

原碼的問題:
以正負(fù)1來說明問題,先來看1+(-1)的計算過程:

1 + (-1)=[0000 0001]原+[1000 0001]原=[1000 0010]原=-2

1+(-1)=0,但是用原碼來算結(jié)果卻是-2,原碼的加法沒有問題,但是減法卻出現(xiàn)了問題。

四、補(bǔ)碼

為了解決原碼做減法時出現(xiàn)的問題,出現(xiàn)了反碼,我們用其他的方式來表示負(fù)數(shù),使減法的問題用加法去解決。

補(bǔ)數(shù)的思想:
要了解補(bǔ)碼的思想就要知道“?!?、“同余”、“補(bǔ)數(shù)”的概念。

在日常生活中,常會遇到“補(bǔ)數(shù)”的概念。計算機(jī)組成原理(唐朔飛)中舉了一個時鐘的例子,現(xiàn)在是6點鐘,要到達(dá)3點鐘的話該怎么辦呢?我們可以順時針方向?qū)r針移動9小時,或是逆時針移動3小時,我們都可以到達(dá)3點鐘,假設(shè)順時針轉(zhuǎn)為正,逆時針轉(zhuǎn)為負(fù),則有:

6 - 3 = 6 + 9,3和15都代表3點鐘

鐘表時針轉(zhuǎn)一圈能代表12個小時,在數(shù)學(xué)上稱12為模,寫作mod 12,對于mod 12而言,+9和-3互為補(bǔ)數(shù),3和15是同余關(guān)系,記作3≡15 (mod 12),3 + 12 = 15.

其實就相當(dāng)于沒到12點就丟失,從0點重新開始。

對于時鐘運(yùn)算,減去一個數(shù),是可以等同于加上另外一個正數(shù),例如:6 - 3 = 6 - 3 + 12 = 6 + 9
其實相當(dāng)于6-3加上模,即相當(dāng)于是時鐘多走了一圈,所以3和15是等價的。

將補(bǔ)數(shù)的概念用到計算機(jī)中,便出現(xiàn)了補(bǔ)碼這種機(jī)器數(shù)。

補(bǔ)碼:正數(shù)的反碼是其本身,負(fù)數(shù)的補(bǔ)碼是在其原碼的基礎(chǔ)上, 符號位不變, 其余各位取反, 最后+1. (即在反碼的基礎(chǔ)上+1),這里只是便于計算才這樣說。

對于補(bǔ)碼,相當(dāng)于是模加上真值,就如同上面的6+(-3),-3就是真值。
整數(shù)補(bǔ)碼的定義為:


式中,x為真值,n為整數(shù)的位數(shù)(對于8位二進(jìn)制數(shù),那么這里的n就為7,第一位是符號位)。

整數(shù)補(bǔ)碼定義中mod 2n+1的由來:
以8位二進(jìn)制為例,整數(shù)的位數(shù)是n=7,8位二進(jìn)制可以表示的最小值是:0000 0000,最大值是:1111 1111,從0到255,即可以表示28=256個數(shù)字,所以整數(shù)補(bǔ)碼的模是2n+1,即mod 2n+1。

原碼中的-0在補(bǔ)碼中是什么?
對于-0,根據(jù)補(bǔ)碼的定義,[-0]補(bǔ)=100000-10000=10000,其實在補(bǔ)碼中-0是不存在的,這也是補(bǔ)碼出現(xiàn)的原因之一,這里的10000只是一種表示方式,所以補(bǔ)碼比原碼能多表示一個數(shù),這個數(shù)就是-2n。

例如:
當(dāng)x=+1010時,[x]補(bǔ)=0,1010;
當(dāng)x=-1101時,[x]補(bǔ)=2n+1 + x = 25 - 1101 = 100000 - 1101 = 1,0011

負(fù)數(shù)的補(bǔ)碼是在其原碼的基礎(chǔ)上, 符號位不變, 其余各位取反, 最后+1,計算方式的由來:
分析:假如x=-1011,[x]補(bǔ)=25-1011,我們把25改寫成100000=11111+00001,可以得到:

[x]補(bǔ) = 25 + x = 11111 + x + 00001

因為x是負(fù)數(shù),我們可以用-x1x2x3x4來表示,單項的xi不是0就是1,上面式子可以改寫為:

[x]補(bǔ) = 25 + x = 11111 - x1x2x3x4 + 00001

因為1減去1得0,減去0得1,負(fù)數(shù)-x1x2x3x4的原碼為1,x1x2x3x4,所以式子中11111 - x1x2x3x4就相當(dāng)于是對原碼的取反操作,最后再+00001,所以得到上面負(fù)數(shù)求補(bǔ)碼的計算方式。

小數(shù)補(bǔ)碼的定義為:


式中,x為真值,n為小數(shù)的位數(shù)。

小數(shù)補(bǔ)碼定義中mod 2的由來:

小數(shù)的最大值為:1.1111,當(dāng)增加1時(1.1111+1),得到小數(shù)補(bǔ)碼的模是2,所以小數(shù)補(bǔ)碼是:mod 2。

例如:
當(dāng)x=+0.0110時,[x]補(bǔ)=0.1001;
當(dāng)x=-0.0110時,[x]補(bǔ)=2 + x = 10.0000 - 0.0110 = 1.1010
當(dāng)x=0時,
[+0.0000]補(bǔ)=0.0000;
[-0.0000]補(bǔ)=2 + (-0.0000) = 10.0000 - 0.0000 = 0.0000;
顯然[+0]補(bǔ)=[-0]補(bǔ)=0.0000,即補(bǔ)碼中的“零”只有一種表示形式。

補(bǔ)碼的符號位擴(kuò)展:
1、補(bǔ)碼的正負(fù)小數(shù)符號位擴(kuò)展就是在末尾加0即可,例如:1.1101擴(kuò)展為1.1101 0000
2、補(bǔ)碼的正數(shù)符號位擴(kuò)展在最高位前面加0即可,例如:0101擴(kuò)展為0000 0101
3、補(bǔ)碼的負(fù)數(shù)符號位擴(kuò)展在最高位前面加1既可以,例如:1010擴(kuò)展為1111 1010

五、反碼

反碼通常用來作為由原碼求補(bǔ)碼或者由補(bǔ)碼求原碼的中間過渡。
反碼:正數(shù)的反碼是其本身,負(fù)數(shù)的反碼是在其原碼的基礎(chǔ)上,符號位不變,其余各個位取反。這個方法只是利于計算,但是并不代表反碼的真正含義,可以把它忘記

[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反

整數(shù)反碼的定義為:


式中,x為真值,n為整數(shù)的位數(shù)。
例如:
當(dāng)x=+1101時,[x]=0,1101(用逗號將符號位和數(shù)值部分隔開)
當(dāng)x=-1101時,[x]=(x4+1 - 1)+x=1,1111-1101=1,0010

小數(shù)反碼的定義為:


式中,x為真值,n為小數(shù)的位數(shù)。
例如:
當(dāng)x=+0.0110時,[x]=0.0110;
當(dāng)x=-0.0110時,[x]=(2-2-4)+x=1.1111-0.0110=1.1001;
當(dāng)=0時,
[+0.0000]=0.0000;
[-0.0000]=(10.0000-0.0001)-0.0000=1.1111;
由上可見[+0]和[-0]是有兩種表現(xiàn)方式。

反碼的問題:
反碼中0有兩種表示方式,0000 0000和1111 1111,這導(dǎo)致在實際計算中每當(dāng)跨過0一次,就有一個單位的誤差,所以需要+1,即補(bǔ)碼的方式。

六、移碼

因為補(bǔ)碼符號位和數(shù)值一起編碼,所以很難從補(bǔ)碼上直接判斷出其真值的大小,而用移碼就可以很直觀的看判斷出來。

移碼的定義:


式中,x為真值,n為整數(shù)的位數(shù)。
例如:
當(dāng)x=10100時,[x]=25+10100=1,10100
當(dāng)x=-10100時,[x]=25-10100=0,01100
可以直接看出10100>-10100

利用移碼的這一特點,當(dāng)浮點數(shù)的階碼用移碼表示時,就能很方便的判斷階碼的大小。

移碼相當(dāng)于補(bǔ)碼的符號位取反。

對于補(bǔ)碼來說是存在符號位的,使用移碼就相當(dāng)于把補(bǔ)碼的負(fù)數(shù)部分往上移動,使得最小值變?yōu)?,而不是負(fù)數(shù)。

移碼更詳細(xì)的用處以后再研究。


寫在最后:

  • 如果文章中有錯誤或是表達(dá)不準(zhǔn)確的地方,歡迎大家評論中指正,以便我完善。
  • 文章我也會根據(jù)所學(xué)到新的知識不斷更新。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容