計算機系統結構-數據表示
[TOC]數據結構
數據表示:數據表示是指能由計算機硬件直接識別和引用的數據類型。(例如定點數浮點數)spa
表如今什麼地方:表如今它有對這種數據類型進行操做的指令和功能部件。code
數據結構種類:串,隊,列,棧,陣列,鏈表,樹,圖blog
什麼是數據結構:它反映了應用中要用到的各類數據元素和或信息單元之間的結構關係。教程
數據表示
自定義數據表示
自定義數據表示,包括標誌符的數據表示、數據描述符的數據表示。編譯
標誌符的數據表示class
標識符的數據表示:指用於標識數據類型,例如負數、幾機制、浮點型等;效率
原理:讓計算機中每一個數據都帶有類型標誌符。原理
優勢:可簡化指令系統和編譯程序,便於不一樣數據類型的自動校驗和檢驗。書籍
缺點:一個標誌位只能對一個數據進行描述。描述效率不高。
咱們能夠想象成 C# 中的值類型。
數據描述符的數據表示
跟標識符的數據表示相似,主要區別在於標識符的數據表示的標誌符是跟數據在一塊兒的;數據描述符的數據表示中,數據描述符是跟數據分開的。
數據描述符中包含數據的各類標誌位、長度、數據地址。
咱們能夠想象成 C# 中的引用類型。
浮點數
對於一個浮點數,10進制狀況下,咱們可使用如下公式表示小數部分
N = ±m * 10^e
N表示浮點數,m表示小數尾數,e表示位數。
例如 1100.1 = 0.1 * 10^3。
上面的是 10 進制狀況下,而在計算機系統中,通常使用 二、八、16進製表示。
所以,計算機表示浮點數的公式以下
S 表示正負,S = 0時,N爲正數,S = 1 時, N爲負數。
m 爲小數尾數。
R<sub>m</sub> 表示階碼的基。
e 表示階碼的值。
浮點數在數據存儲單元中的存儲方式如圖
有些書籍和教程中, 將 e<sub>r</sub> 和 e 位放到一塊兒
浮點數的階碼須要移碼。
出現上面的原理,只是將屬於尾數的符號位(正負)放到了開頭的位置。
原碼:二進制數的最高一位表明正負符號,0表明正號,1表明負號,如下各位給出數值絕對值的表示法。
原理:(-1)<sup>S</sup> ,當 s = 0
時,值爲正數;當 s = 1
時,值爲負數。
零有正零和負零兩種表示形式。
補碼:將一個數轉爲原碼後。
若爲正數,數的補碼和原碼相同,不須要變換。
若爲負數,除首位外,其他位取反,最後一位加 1。
零隻有一種表示形式,即原碼中的正零。
移碼:移碼(又叫增碼)是符號位取反的補碼,通常用指數的移碼減去1來作浮點數,引入的目的是爲了保證浮點數的機器碼爲全0。
移碼與補碼的符號位互爲相反數。
例如將一個數 666666 轉爲 8 進制浮點數格式
666666(int) = 2426052 = 2.426052 * 8^6
以上可知,m = 0.2426052;r<sub>m</sub> = 8;e = 6;
八進制 2426052 的二進制爲 00001010 00101100 00101010
6 的二進制 00000110;移碼爲 10000110。
合併起來就是 <span style="color:red;">10000110</span> + <span style="color:blue;">00001010 00101100 00101010</span>
因此 666666 存儲形式爲 <span style="color:blue;">0</span><span style="color:red;">10000110</span><span style="color:blue;">0001010 00101100 00101010</span>
要注意的是,實際計算是二進制的,上面的計算方法只是爲了更加清晰理解表示方法。
能夠看到,當位數必定時,階碼的位數越大,能夠表示的範圍越大,可是精度變低;
階碼的位數越小,能夠表示的範圍越小,可是精度更高。
浮點數標準
IEEE754 中,規定了單精確度(float)、雙精確度(double) 兩種基本浮點型
Float
那麼階碼的值e 最大爲 2<sup>8-1</sup> ,-127~128 (由於負數須要補碼+1)。
r<sub>m</sub><sup>e</sup> = 2<sup>-127</sup> ~ 2<sup>128</sup>
2<sup>128</sup> 是 r<sub>m</sub><sup>e</sup> 的最大絕對值。
因此上下限範圍是 -3.4028236692094e+38 ~ 3.4028236692094e+38
。
去除多餘的小數,爲 -3.40E+38 ~ +3.40E+38
。
尾數範圍 2<sup>23</sup> = 8388608,一共7位。
因此 Float 精確度只有 7 位。由於每每最後一位是四捨五入後的數,因此能徹底保證準確度的只有 6 位。
例題
1,求 -666666 在 float 中存儲的形式
解題過程:
將 -666666 轉爲 二進制 爲 10001010 00101100 00101010
。由於負數須要補碼,
因此 反碼11110101 11010011 11010101
,補碼 <span style="color:blue;">11110101 11010011 11010110</span> 。
迴歸正題,
-666666 = -11110101 11010011 11010110,
移動5位 = -1.1110101 11010011 11010110 * 2<sup>23</sup>
e = 23,轉爲 二進制爲存儲數 0001 0111,移碼 <span style="color:red;">1001 0111</span>。
最後 <span style="color:blue;">1</span> <span style="color:red;">1001 0111</span> <span style="color:blue;">1110101 11010011 11010110</span> 。
2,求 -6.66666 在 float 中存儲的形式
將 6 轉爲二進制爲 0000 0110
0.66666 轉爲二進制爲 0.10101010101010100011101011010001100011010010010111111... ...
由於留給存儲尾數的空間只有 24 位,6已經使用了一位,因此
0.66666 取16 位爲 0.1010101010101010,其他精度丟失。
6.66666 轉爲二進制爲 <span style="color:blue;">0000 0110 . 10101010 10101010</span>
倒過來 110.1010101010101010 轉爲 10 進製爲 6.666656494140625
,精度發生變化。
-6.66666 原碼 <span style="color:blue;">1000 0110 . 10101010 10101010</span>
補碼 <span style="color:blue;">1111 1001 . 01010101 01010111</span>
小數點左移 7 位 <span style="color:blue;">1.111 1001 01010101 01010111</span>
因此 6.66666 = <span style="color:blue;">1.111 1001 01010101 01010111</span> * 2<span style="color:red;"><sup>7</sup></span>
7 轉爲二進制爲 0000 0111,移碼爲 <span style="color:red;">1000 0111</span>
最後 <span style="color:blue;">1</span> <span style="color:red;">1000 0111</span> <span style="color:blue;">111 1001 01010101 01010111</span>
能夠看到,上面已經發生精度丟失了。