到目前為止,我們學(xué)習(xí)了十進(jìn)制频鉴、二進(jìn)制栓辜、八進(jìn)制、十六進(jìn)制等用來代表實(shí)際數(shù)值的數(shù)垛孔,稱為真值藕甩,這些數(shù)我們?cè)偃粘I钪卸紩?huì)使用到,那么在計(jì)算機(jī)中數(shù)值是怎么來表示的呢周荐?
??數(shù)在計(jì)算機(jī)中的表示形式統(tǒng)稱為機(jī)器數(shù)狭莱。計(jì)算機(jī)中處理數(shù)據(jù)及運(yùn)算都是采用二進(jìn)制,通常規(guī)定機(jī)器數(shù)用八位二進(jìn)制表示概作。實(shí)用的數(shù)據(jù)有正數(shù)和負(fù)數(shù)腋妙,因?yàn)橛?jì)算機(jī)只能表示0、1兩種狀態(tài)讯榕,數(shù)據(jù)的正號(hào)“+”或負(fù)號(hào)“-”骤素,在計(jì)算機(jī)里就用一位二進(jìn)制的0或1來區(qū)別,通常放在最高位愚屁,成為符號(hào)位济竹。 符號(hào)位數(shù)值化之后,為能方便的對(duì)機(jī)器數(shù)進(jìn)行算術(shù)運(yùn)算霎槐、提高運(yùn)算速度送浊,計(jì)算機(jī)設(shè)計(jì)了多種符號(hào)位與數(shù)值一起編碼的方法,最常用的機(jī)器數(shù)表示方法有:原碼栽燕、反碼罕袋、補(bǔ)碼和移碼改淑,下面就分別介紹一下它們的表示方法。
0X01 原碼浴讯、反碼朵夏、補(bǔ)碼和移碼
- 原碼:正數(shù)是其二進(jìn)制本身;負(fù)數(shù)是符號(hào)位為1,數(shù)值部分取X絕對(duì)值的二進(jìn)制榆纽。
- 反碼:正數(shù)的反碼和原碼相同仰猖;負(fù)數(shù)是符號(hào)位為1,其它位是原碼取反。
- 補(bǔ)碼:正數(shù)的補(bǔ)碼和原碼奈籽,反碼相同饥侵;負(fù)數(shù)是符號(hào)位為1,其它位是原碼取反衣屏,未位加1躏升。(或者說負(fù)數(shù)的補(bǔ)碼是其絕對(duì)值反碼未位加1)
- 移碼:將符號(hào)位取反的補(bǔ)碼(不區(qū)分正負(fù))
舉個(gè)例子以一個(gè)字節(jié)8位說明:
編碼 | 10810(sbyte) | -10810(sbyte) |
---|---|---|
原碼 | 01101100 | 11101100 |
反碼 | 01101100 | 10010011 |
補(bǔ)碼 | 01101100 | 10010100 |
移碼 | 11101100 | 00010100 |
注:加粗的數(shù)字為符號(hào)位,補(bǔ)碼在線工具
??移碼表示法是在數(shù)X上增加一個(gè)偏移量來定義的狼忱,常用來表示浮點(diǎn)數(shù)中的階碼膨疏,所以是整數(shù)。如果機(jī)器字長(zhǎng)為n钻弄,規(guī)定偏移量為2(n-1)佃却。若X是整數(shù),則X移=2^(n-1)+X
例子:假設(shè)字長(zhǎng)為8窘俺,以上面的108為例
108移=10000000+01101100=11101100
-108移=10000000+10010100=00010100
0X02 補(bǔ)碼求原碼
已知一個(gè)數(shù)的補(bǔ)碼饲帅,求原碼的操作分兩種情況:
如果補(bǔ)碼的符號(hào)位為“0”,表示是一個(gè)正數(shù)瘤泪,所以補(bǔ)碼就是該數(shù)的原碼灶泵。
如果補(bǔ)碼的符號(hào)位為“1”,表示是一個(gè)負(fù)數(shù)均芽,求原碼的操作可以是:符號(hào)位為1丘逸;其余各位取反单鹿,然后再整個(gè)數(shù)加1掀宋。
0X03 補(bǔ)碼加、減運(yùn)算公式
- 在做補(bǔ)碼加減法時(shí)仲锄,只需將符號(hào)位和數(shù)值部分一起參與運(yùn)算劲妙,并且將符號(hào)位產(chǎn)生的進(jìn)位丟掉即可
- 補(bǔ)碼加法公式
??[X+Y]補(bǔ) = [X]補(bǔ) + [Y]補(bǔ) - 補(bǔ)碼減法公式
??[X-Y]補(bǔ) = [X]補(bǔ)-[Y]補(bǔ) = [X]補(bǔ) + [-Y]補(bǔ)
其中:[-Y]補(bǔ)稱為負(fù)補(bǔ),求負(fù)補(bǔ)的辦法是:對(duì)補(bǔ)碼的每一位(包括符合位)求反,且未位加1.
假設(shè)字長(zhǎng)為8的計(jì)算機(jī)sbyte類型所能表示的最大數(shù)是11111111儒喊,若再加1稱為100000000(9位)镣奋,但因只有8位,最高位1自然丟失怀愧。又回了00000000侨颈,所以字長(zhǎng)為8的二進(jìn)制系統(tǒng)的模為2^8余赢。
0X04 為何要使用原碼, 反碼和補(bǔ)碼
在開始深入學(xué)習(xí)前, 我的學(xué)習(xí)建議是先"死記硬背"上面的原碼, 反碼和補(bǔ)碼的表示方式以及計(jì)算方法.
現(xiàn)在我們知道了計(jì)算機(jī)可以有三種編碼方式表示一個(gè)數(shù). 對(duì)于正數(shù)因?yàn)槿N編碼方式的結(jié)果都相同:
[+1] = [00000001]原 = [00000001]反 = [00000001]補(bǔ)
所以不需要過多解釋. 但是對(duì)于負(fù)數(shù):
[-1] = [10000001]原= [11111110]反= [11111111]補(bǔ)
可見原碼, 反碼和補(bǔ)碼是完全不同的. 既然原碼才是被人腦直接識(shí)別并用于計(jì)算表示方式, 為何還會(huì)有反碼和補(bǔ)碼呢?
首先, 因?yàn)槿四X可以知道第一位是符號(hào)位, 在計(jì)算的時(shí)候我們會(huì)根據(jù)符號(hào)位, 選擇對(duì)真值區(qū)域的加減. (補(bǔ)碼的絕對(duì)值稱為真值即去掉符號(hào)位的二進(jìn)制數(shù)字). 但是對(duì)于計(jì)算機(jī), 加減乘數(shù)已經(jīng)是最基礎(chǔ)的運(yùn)算, 要設(shè)計(jì)的盡量簡(jiǎn)單. 計(jì)算機(jī)辨別"符號(hào)位"顯然會(huì)讓計(jì)算機(jī)的基礎(chǔ)電路設(shè)計(jì)變得十分復(fù)雜! 于是人們想出了將符號(hào)位也參與運(yùn)算的方法. 我們知道, 根據(jù)運(yùn)算法則減去一個(gè)正數(shù)等于加上一個(gè)負(fù)數(shù), 即: 1-1 = 1 + (-1) = 0 , 所以機(jī)器可以只有加法而沒有減法, 這樣計(jì)算機(jī)運(yùn)算的設(shè)計(jì)就更簡(jiǎn)單了.
于是人們開始探索 將符號(hào)位參與運(yùn)算, 并且只保留加法的方法. 首先來看原碼:
計(jì)算十進(jìn)制的表達(dá)式: 1-1=0
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原= [10000010]原 = -2
如果用原碼表示, 讓符號(hào)位也參與計(jì)算, 顯然對(duì)于減法來說, 結(jié)果是不正確的.這也就是為何計(jì)算機(jī)內(nèi)部不使用原碼表示一個(gè)數(shù).
為了解決原碼做減法的問題, 出現(xiàn)了反碼:
計(jì)算十進(jìn)制的表達(dá)式: 1-1=0
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反+ [1111 1110]反= [1111 1111]反= [1000 0000]原= -0
發(fā)現(xiàn)用反碼計(jì)算減法, 結(jié)果的真值部分是正確的. 而唯一的問題其實(shí)就出現(xiàn)在"0"這個(gè)特殊的數(shù)值上. 雖然人們理解上+0和-0是一樣的, 但是0帶符號(hào)是沒有任何意義的. 而且會(huì)有[0000 0000]原和[1000 0000]原兩個(gè)編碼表示0.
于是補(bǔ)碼的出現(xiàn), 解決了0的符號(hào)以及兩個(gè)編碼的問題:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]補(bǔ)+ [1111 1111]補(bǔ)= [0000 0000]補(bǔ)=[0000 0000]原
這樣0用[0000 0000]表示, 而以前出現(xiàn)問題的-0則不存在了.而且可以用[1000 0000]表示-128:
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]補(bǔ)+ [1000 0001]補(bǔ)= [1000 0000]補(bǔ)
-1-127的結(jié)果應(yīng)該是-128, 在用補(bǔ)碼運(yùn)算的結(jié)果中, [1000 0000]補(bǔ)就是-128. 但是注意因?yàn)閷?shí)際上是使用以前的-0的補(bǔ)碼來表示-128, 所以-128并沒有原碼和反碼表示.(對(duì)-128的補(bǔ)碼表示[1000 0000]補(bǔ)算出來的原碼是[0000 0000]原, 這是不正確的)
使用補(bǔ)碼, 不僅僅修復(fù)了0的符號(hào)以及存在兩個(gè)編碼的問題, 而且還能夠多表示一個(gè)最低數(shù). 這就是為什么8位二進(jìn)制, 使用原碼或反碼表示的范圍為[-127, +127], 而使用補(bǔ)碼表示的范圍為[-128, 127].
因?yàn)闄C(jī)器使用補(bǔ)碼, 所以對(duì)于編程中常用到的32位int類型, 可以表示范圍是: [-231, 231-1] 因?yàn)榈谝晃槐硎镜氖欠?hào)位.而使用補(bǔ)碼表示時(shí)又可以多保存一個(gè)最小值.
總結(jié):
- 原碼負(fù)數(shù)不能參與運(yùn)算并且不能做減法運(yùn)算
- 反碼的+0和-0的反碼不相同
- -128在運(yùn)算中的補(bǔ)碼是 [1000 0000]補(bǔ),并沒有原碼和反碼表示
引用的文章:
http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html
http://blog.csdn.net/peng_weida/article/details/7931990