# 數(shù)據(jù)存儲(chǔ)和進(jìn)制轉(zhuǎn)化
標(biāo)簽(空格分隔): 基礎(chǔ)知識(shí)
---
傳統(tǒng)的計(jì)算機(jī)都是基于馮諾依曼體系,用集成電路中二極管的通電和斷電,高電平和低電平等狀態(tài)位來表示1和0(就這么個(gè)意思,簡(jiǎn)要描述錯(cuò)誤之處請(qǐng)指出),故計(jì)算機(jī)只能識(shí)別二進(jìn)制的0、1。現(xiàn)實(shí)世界的數(shù)據(jù)都是通過一定的規(guī)則轉(zhuǎn)化為二進(jìn)制數(shù)據(jù)流然后才能在計(jì)算機(jī)中存儲(chǔ)和運(yùn)算.
1.進(jìn)制的概念: 進(jìn)制也就是進(jìn)位制,是人們規(guī)定的一種進(jìn)位方法。 對(duì)于任何一種進(jìn)制---X進(jìn)制,就表示某屏幕快照 2016-12-23 下午2.10.18一位置上的數(shù)運(yùn)算時(shí)是逢X進(jìn)一位。 十進(jìn)制是逢十進(jìn)一,十六進(jìn)制是逢十六進(jìn)一,二進(jìn)制就是逢二進(jìn)一
在采用進(jìn)位計(jì)數(shù)的數(shù)字系統(tǒng)中,如果只用r個(gè)基本符號(hào)表示數(shù)值,則稱為r進(jìn)制(Radix-r Number System),r稱為該數(shù)制的基數(shù)(Radix)。不同的數(shù)制的共同特點(diǎn)如下:
(1)、每一種數(shù)制都有篤定的符號(hào)集。例如,十進(jìn)制數(shù)制的基本符號(hào)有十個(gè):0,1,2。。。,9。二進(jìn)制數(shù)制的基本符號(hào)有兩個(gè):0和1.
2、每一種數(shù)制都使用位置表示法。即處于不同位置的數(shù)符所代表的值不同,與它所在位的權(quán)值有關(guān)。
例如:十進(jìn)制1234.55可表示為
1234.55=1×10^3+2×10^2+3×10^1+4×10^0+5×10^(-1)+5×10^(-2)
可以看出,各種進(jìn)位計(jì)數(shù)制中權(quán)的值恰好是基礎(chǔ)的某次冪。因此,對(duì)任何一種進(jìn)位計(jì)數(shù)制表示的數(shù)都可以寫成按權(quán)展開的多項(xiàng)式。
3. 八進(jìn)制和十六進(jìn)制
人類一般的思維方式是十進(jìn)制,編碼人員看到一堆0 1的二進(jìn)制數(shù)肯定蛋疼,例如一個(gè)最簡(jiǎn)單char 類型字符 a的二進(jìn)制表示: 0010 0110,直接用十進(jìn)制又無法準(zhǔn)確計(jì)算機(jī)思維方式(二進(jìn)制 0B).所以出現(xiàn)了八進(jìn)制和十六進(jìn)制,當(dāng)然十六進(jìn)制的運(yùn)用更加廣泛,例如一個(gè)int型的32位數(shù)字,用八進(jìn)制表示 32/3 = 2,余2也就是說我們每個(gè)前面要加2個(gè)0.學(xué)過編程的肯定知道變量的地址一般都是用十六進(jìn)制表示 :
printf(" c address : %p\n",&c);
輸出: c address : 0x7fff5fbff73c
所以說用十六進(jìn)制表達(dá)二進(jìn)制字符串無疑是最佳的方式,這就是八進(jìn)制和十六進(jìn)制出現(xiàn)的原因。
4.進(jìn)制間的轉(zhuǎn)換
常用的進(jìn)制有 二進(jìn)制 八進(jìn)制 十進(jìn)制 十六進(jìn)制
- 1.二進(jìn)制,八進(jìn)制,十六進(jìn)制 -> 十進(jìn)制
都是按權(quán)展開多項(xiàng)式相加得到十進(jìn)制
示例:
二進(jìn)制1010.101 ->? 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 0 * 2^0 + 1*2^(-1) + 0 * 2^(-2) + 1*2^-3=10.6875
八進(jìn)制? 13.1到十進(jìn)制 1*8^1 + 3*8^0 + 1*8^(-1) = 11.125
十六進(jìn)制13.1到十進(jìn)制 1*16^1 + 3*16^0 + 1*16^(-1) = 19.0625
- 2.十進(jìn)制 -> 二進(jìn)制 八進(jìn)制 十六進(jìn)制? 都是按照整數(shù)部分除以基數(shù)(r)取余,小數(shù)部分乘以基數(shù)(r)取整.
十進(jìn)制10.25 到二進(jìn)制
10/2 --0
5/2? --1
2/2? --0
1/2? --1
0.25 * 2 = 0.5 --? 0
0.5 * 2? = 1? ? --? 1
整數(shù)部分: 1010
小數(shù)部分: 01
所以到二進(jìn)制 1010.01,
同理八進(jìn)制和十六進(jìn)制,只是基數(shù)改變而已
- 3 二進(jìn)制 <----> 八進(jìn)制 十六進(jìn)制
二進(jìn)制轉(zhuǎn)化為八進(jìn)制: 從小數(shù)點(diǎn)起,二進(jìn)制每三個(gè)數(shù)字分為一組,若不夠小數(shù)點(diǎn)前面的在每組前面加0,后面的在每組后面就0,然后把每組數(shù)轉(zhuǎn)化為相應(yīng)的十進(jìn)制數(shù)就可以了
10010101.101 - (010 010 101) . (101) = (2 2 5) . (5) = 225.5
八進(jìn)制轉(zhuǎn)二進(jìn)制:? ? 八進(jìn)制數(shù)每一位轉(zhuǎn)化為二進(jìn)制數(shù),拼起來
257.56 = (10 101 111). (101 110) = 10101111.101110
二進(jìn)制轉(zhuǎn)十六進(jìn)制: 小數(shù)點(diǎn)起,二進(jìn)制數(shù)每4個(gè)二進(jìn)制位分為一組,如果不夠小數(shù)點(diǎn)前面的在每組前面加0,后面的在每組后面加0,然后把每組數(shù)轉(zhuǎn)化為相應(yīng)的十進(jìn)制數(shù)就行,注意一點(diǎn)就是
10->A , 11->B , 12->C , 13->D , 14->E, 15->F 大于等于10的用字母表示(不區(qū)分大小寫)
10101111.10111? -> (1010 1111).(1011 1000) = (12 16).(13 9) = AF.B8
數(shù)據(jù)的分類
編程中數(shù)據(jù)類型一般分為基本數(shù)據(jù)類型和復(fù)合數(shù)據(jù)類型,特別是面向?qū)ο缶幊讨械念惡蛯?duì)象就是一種典型的復(fù)合數(shù)據(jù)類型.本質(zhì)上復(fù)合數(shù)據(jù)類型也是由基本數(shù)據(jù)類型構(gòu)成.
以C語言為例,基本數(shù)據(jù)類型有 字符型char, 整型(無符號(hào) 帶符號(hào) 長(zhǎng) 短整型等等),實(shí)現(xiàn)(float,double),bool型(其實(shí)bool型也是整型,只不過用宏定義聲明了而已)
先說基本數(shù)據(jù)類型
1.無符號(hào)
unsigned int b = 1; //
printf(" c address : %#x\n",b);
輸出 : 0x7b (0x1)
可以看出直接就是二進(jìn)制數(shù)表示的
2.帶符號(hào)
對(duì)于帶符號(hào)整數(shù),最高位是符號(hào)位.0代表+,1代表-
int c = -1;
printf(" c address : %#x\n",c);
輸出: 0xffffffff (11111111111111111111111111111111)
輸出和無符號(hào)完全不一樣,這是因?yàn)閹Х?hào)整型和無符號(hào)整型的二進(jìn)制表示方式不一樣
這又涉及到另外一個(gè)問題,原碼,反碼和補(bǔ)碼
- 1.原碼:
數(shù)值X的原碼記做[X]原,若果機(jī)器字長(zhǎng)為n(即用n個(gè)二進(jìn)制位表示數(shù)據(jù)).最高位符號(hào)位,其余的n-1表示數(shù)值的絕對(duì)值, 數(shù)值0的原碼有兩種表示方式: [+0]原 = 0000 0000 , [-0]原 = 1000 0000
例子: 字長(zhǎng)n為8的數(shù)字
[+1] = 0000 0001? ? ? ? ? [-1] = 1000 0001
[+127] = 0111 111? ? ? ? ? [-127] = 1111 1111
兩者相加明顯有問題,這又引出了下一個(gè)問題-反碼
- 2.反碼
數(shù)值X的反碼記做[X]反,最高位是符號(hào)位,0為正1為負(fù).正數(shù):反碼=原碼,負(fù)數(shù): 反碼=原碼絕對(duì)值按位取反,數(shù)值0的反碼有兩種表示方式 [+0] = 0000 0000, [-0] = 1111 1111,
例子: 字長(zhǎng)n為8的數(shù)字
[+1] = 0000 0001? ? ? ? ? ? [-1] = 1111 1110
[+127] = 0111 1111? ? ? ? ? [-127] = 1000 0000
用反碼進(jìn)行計(jì)算? ? 1111 1110 -> 1000 0001
-1 + 1 =? 0? |? ? (1111 1110)反 + (0000 0001)?反 = (1000 0000)原=? 0沒有問題
1+(-2)=-1? |? ? (0000 0001)反 + (1111 1101)反 = (1000 0001)原 = -1 沒有問題
-1 + 2 = 1? |? ? (1111 1110)反 + (0000 0010)反 = (0000 0000)原 = 0? 發(fā)生了溢出
所以反碼也是不對(duì)的,這就又引出了補(bǔ)碼這個(gè)概念
- 3.補(bǔ)碼
數(shù)值X的補(bǔ)碼記做[X]補(bǔ),如果數(shù)字字長(zhǎng)為n,最高位為符號(hào)位,0代表正好,1代表負(fù)號(hào).正數(shù)的補(bǔ)碼和原碼反碼都相同,負(fù)數(shù)的補(bǔ)碼等于反碼在末尾加1.數(shù)值0有唯一的補(bǔ)碼 [+0] = 0000 0000 [-0] = 0000 0000
例子: 字長(zhǎng)n=8的數(shù)字
[+1]補(bǔ) = 0000 0001? ? ? ? ? [-1]補(bǔ) = 1111 1111
[+127]補(bǔ) = 0111 1111? ? ? ? [-127]補(bǔ) = 1000 0001
[+45]補(bǔ)=0010 1101? ? ? ? ? [-45]補(bǔ)=1101 0011
反碼的運(yùn)算:
-1 + 1 = 0? ? ? ? (1111 1111)補(bǔ) + (0000 0001)補(bǔ) = (0000 0000)補(bǔ) = (0000 0000)原 沒有問題
-2 + 1 = -1? ? ? (1111 1110)補(bǔ) +? (0000 0001補(bǔ) = (1111 1111)補(bǔ) = (1000 0001)原 沒有問題
-1 + 2 = 1? ? ? ? (1111 1111)補(bǔ) + (0000 0010)補(bǔ) = (0000 0001)補(bǔ) = (0000 0001)原
沒有問題
- 浮點(diǎn)數(shù)的存儲(chǔ)
根據(jù)IEEE754標(biāo)準(zhǔn),任意一個(gè)浮點(diǎn)數(shù)V可以表示為以下形式
如十進(jìn)制V = 9.0,表示為二進(jìn)制 1001.0,相當(dāng)于 1.001 * 2^3, 則 S = 0, M=1.001,E = 3;
同理十進(jìn)制V = -9.0,表示為二進(jìn)制 -1001.0*2^3,則S = 1,M=1.001,E=3;
參考:
http://blog.csdn.net/lonelyroamer/article/details/7670869
http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html