計算機內資料的儲存是以二進位制數的補碼形式存在的。
那麼什麼是補碼呢?
這裡要涉及到二進位制數的原碼、反碼、補碼等儲存方式的概念。
機器編碼
機器編碼有原碼、反碼、補碼、移碼、階碼等。
原碼
原碼概念
計算機中所有的二進位制數均用0、1編碼表示,數字的正、負也不例外,如果乙個機器數字長是n的話,約定最左邊1位作為符號位,其餘n-1位用於表示數值。在符號位上,用0表示正,用1表示負。數值位表示真值的絕對值。凡不足n-1位的,小數在最低位右邊增加0;整數則在數值位的最高位(不是符號位)左邊增加0,補足n-1為。這種計算機的編碼形式叫做原碼。
原碼的表示形式:符號位+二進位制數值
例如十進位制數12,它的二進位制原碼為[0000 1100],最高位0表示符號+(正)。
有符號的二進位制編碼如下圖所示:
圖 1 8bit機器
例如在8bit的機器內,小數和整數的表示:
小數:[+0.1011]原=0.1011000,補足8位:0
1011
000[-0.1011]原=1.1011000,補足8位:1
1011
000整數:[+1011]原=00001011,補足8位:0
0001
011[-1011]原=10001011,補足8位:1
0001
011**中的小數點只是在書寫時為了清晰可見,在機器中並不出現。
原碼的特徵
◇最高位0表示正,1表示負。其餘二進位制數是該數字的絕對值的二進位制位。
◇原碼簡單易懂,接近人的思維。
例如:我們用8位二進位制表示乙個數,+11的原碼為00001011,-11的原碼就是10001011,這個很好理解。
◇加、減運算複雜,相減時,被減數不夠減時,需要向高位借位。原碼的符號位不能直接參與運算。
乙個字長為n(即n bit)的機器數能表示不同的數字的個數是固定的:2n個,n=8時,2n=256。如果用來表示有符號數,那麼取值範圍是-2n-1~+2n-1。n=8時這個範圍即是-128~127。但是在不考慮數的的正負時,就不需要用1位二進位制數來表示符號位,n位機器數全部用來表示數值,這時表示數的取值範圍是0~2n-1,n=8時的範圍就是0~255。沒有符號位的數,稱為無符號數。
◇存在加、減、乘、除四種運算,增加cpu的複雜度。
◇0的表示不唯一,有+0和-0之分。
反碼
反碼是數值儲存的一種,多應用於系統環境設定,如linux平台的目錄和檔案的預設許可權的設定umask,就是使用反碼原理。
反碼運算不方便,也沒有在計算機中得以應用。
◆反碼表示法規定
◇正數的反碼與其原碼相同;
[01010]原=[01010]反
◇負數的反碼是對其絕對值正數的原碼逐位取反,取反時包含符號位。
例如,對二進位制數10010的原碼求反碼:
[10010]原碼
=[00010]取正(1.先對原碼取其絕對值。)
=[11101]取反(2.對得到的絕對值取反,取反時包括符號位。)
注意
:其實,求
負數的反碼
,也可以說是負數的原碼符號位不動,其餘取反。
負數原碼的反碼 = ~|負數|,~為取反的意思。
如下:如:原碼10010的反碼可以這樣求得:
[10010]原碼=[11101]反碼----符號位不動,其餘逐位取反。
那麼原碼(10010)2的反碼(11101)2就是表示十進位制數(-2)10。反碼並不是十進位制數在計算機中的二進位制表現形式,在計算機中表示的二進位制數是補碼。那麼什麼是補碼呢?接著往下看。
移碼
表示數值平移n位,n稱為移碼量。移碼主要表示浮點數的階碼的儲存。
補碼
補碼的概念
在計算機系統中,二進位制數值一律用補碼來表示和儲存。
補碼的設計目的是:
◇使符號位能與有效值部分一起參加運算,從而簡化運算規則。
◇補碼與原碼相互轉換,其運算過程是相同的,不需要額外的硬體電路。
◇使減法運算轉換為加法運算,進一步簡化計算機中運算器的線路設計,所有這些轉換都是在計算機的最底層進行的。
補碼表示法規定
補碼是由原碼轉化而來,那麼轉化規則是:
◇正數的補碼與其原碼相同。
正數的補碼 = 正數的原碼
(10)10 =[0000 1010]原
=[0000 1010]補
◇負數的補碼是在取其反碼之後加1。
負數的補碼 = 負數原碼的反碼+1
負數原碼的反碼 = ~|負數|
(-10)10 =[1000 1010]原
=[1111 0101]反+[0000 0001]即1
=[1111 0110]補
例題:把十進位制(10)10和(-10)10轉為二進位制補碼表示。
1).如果十進位制數為正,如(10)10,那麼:
(10)10=[0000 1010]原
=[0000 1010]反----對於正數,原碼=反碼
=[0000 1010]補----對於正數,反碼=補碼
所以(10)10 在計算機中的二進位制補碼形式為:(0000 1010)2。
總結:如果十進位制數的為正,原碼=補碼。原碼即是二進位制數的表示。
2).如果十進位制數符號為負,如(-10)10,那麼:
(-10)10=[1000 1010]原
=[1111 0101]反+1
=[1111 0110]補
所以(10)10 在計算機中的二進位制補碼形式為:(1111 0110)2。
總結:如果十進位制數為負,把原碼取反數,得到反碼,然後把 反碼+1,即是補碼,也就是二進位制補碼在計算機中的表示。(一句話:原碼取反+1)
3).資料的加減法
如:8 - 9 = -1
計算機中不存在減法,減法是負數的加法。也就是把表示資料的二進位制原碼轉為補碼,進行補碼相加
,再把補碼取反。示例過程示例如下:
因為是補碼運算,所以要對十進位制數進行補碼轉換,然後再運算。
8 - 9= 8 + ( -9 )
= [0000 1000]原 + [1000 1001]原
= [0000 1000]反 +( [1111 0110]反+1)
= [0000 1000]補 + [1111 0111]補
= [1111 1111]補----到了這一步,計算機內算是完成了運算,但是我們要看到是十進位制數的結果。所以就需要把補碼再轉為原碼。
以下是還原過程:
設反碼為x反,那麼
x反 =[1111 1111]補-1
= [1111 1110]反----補碼=反碼+1,那麼反碼=補碼-1,再把反碼取反,得到下一步,即原碼:
= [1000 0001]原----再把二進位制
= (-1)10
即8-9=-1。
其實,這個運算的發明遠沒有那麼簡單,這裡還涉及到餘數,補數。暫略,後補。
(無聊)我我我我的C 筆記(一)
我我我要學c 可是我我我只會c。所以,這篇筆記從乙個c初學者的角度。試著理解c 他在狂笑 概念 所以為什麼要有物件導向程式設計?當然,我們寫乙個hello world算乙個2 3是不需要物件導向的,但是當軟體年得越來越大,越來越多的 量的時候。問題就來了 舉個例子,我要做fifa遊戲,額這個遊戲已經...
我的C 筆記
1,map的key值是不能重複的,char 比較的是位址,所以認為key值相同,所以你只能插入乙個元素 若要用char 做key,需要過載操作符 t1,t2 也就是map的第三個引數,當然你用std string做key的話,可以不用過載這個操作符。2,char轉int char a 1 int b...
我的C 筆記
1,map的key值是不能重複的,char 比較的是位址,所以認為key值相同,所以你只能插入乙個元素 若要用char 做key,需要過載操作符 t1,t2 也就是map的第三個引數,當然你用std string做key的話,可以不用過載這個操作符。2,char轉int char a 1 int b...