计算机系统结构-数据表示
[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>
能够看到,上面已经发生精度丢失了。