1.4 数据和数的表示
冯·诺伊曼模型清楚地将计算机定义为数据处理机,它接受输入数据、处理数据并输出相应的结果。但是,冯·诺伊曼模型并没有定义数据应该怎样存储在计算机中。下面来了解不同类型的数据是怎样以0和1序列的二进制模式存储在计算机内部的。
1.4.1 存储和组织数据
由于计算机是电子设备,所以最好的数据存储方式应该是电子信号,以电子信号的出现和消失的特定方式来存储数据。
日常主要使用的十进制数字是0~9这十种状态中的任何一个,但是不能(至少到目前为止)将这类信息直接存储到计算机内部,其他类型的数据(例如文本、图像、声音、视频等)也同样不能直接存储到计算机当中,除非将这类信息变换成只使用两种状态(0和1序列)的系统。
另一方面,尽管数据只能以一种形式(二进制模式)存储在计算机内部,但在计算机外部却可以表现为多种形式,如数字、文字、图像、音频和视频等。在存储到计算机中之前,数据被组织成许多小的单元,再由这些小的单元组成更大的单元等等。
1.4.2 计算机内部的数据
数据往往是多种类型的混合。例如,银行主要处理数字,但它也需要以文本形式存储客户的名字;图像则通常是图形和文本的混合。最有效的解决方法就是采用统一的数据表示法。所有计算机外的数据类型都采用统一的数据表示法,经过转换后存入计算机,当数据从计算机输出时再还原回来。这种通用的格式称为位模式。
1.位。bit,二进制数字,是存储在计算机中的最小数据单位,即0或1。“位”代表设备的某一状态,这些设备只能处于两种状态中的某一种状态。例如,开关合上或者断开。按惯例用1表示合上状态,用0表示断开状态。电子开关能表示位,换句话说,开关能存储一个位的信息。现在,计算机使用各种各样的两态设备来存储数据。
2.位模式。由于要存储更大的数、文本、图形等,单个“位”并不能解决数据表示问题。为了表示数据的不同类型,可以使用“位模式”,它是一个0和1的序列。例如:1000101010111111展示了由16个位组成的位模式。这就意味着,如果要存储一个由16个位组成的位模式。就需要16个电子开关。如果要存储1000个位模式,每个16位,那么就需要16000个开关。
计算机存储器仅仅将数据以位模式存储,至于位模式是数字类型、文本类型还是其他的数据类型,则由输入/输出设备或程序来解释。换句话说,当数据输入计算机时,它们被编码,当呈现给用户时,它们被解码,如图1-14所示。
图1-14 位模式举例
3.字节。通常长度为8的位模式称为“字节”,这个术语同样被用作测量内存或其他存储设备的大小。例如,一台能存储100万位信息的计算机称其有1兆(M)字节的内存容量。
1MB=1024KB=1024×1024bit
1.4.3 表示数据
位模式可以用来表示不同类型的数据。
1.文本
位模式可以表示任何一个符号。例如,由4个符号组成的“BYTE”文本可采用4个位模式表示,每个模式定义一个符号:BYTE分别表示为1000010、1011001、1010100、1000101。
在一种语言中,位模式需要多少位来表示一个符号,取决于该语言集中有多少个不同的符号。位模式长度与符号数量的关系是个对数关系。例如,如果需要2个符号,位模式长度是1位(log22=1),即0、1;如果需要4个符号,位模式长度是2位(log24=2),即00、01、10和11,这些形式中的任何一种都可用来代表一个字符。同样,3位的位模式有8种不同的形式:000、001、010、011、100、101、110和111。
不同的位模式集合被设计用于表示文本符号,每一个集合被称为“代码”,表示符号的过程称为“编码”。常用的代码有。
(1)ASCII码:美国信息交换标准码,由美国国家标准协会(ANSI)开发。此代码使用7位表示每个符号,即可以定义27=128种不同的符号。
(2)扩展ASCII码:为了使每个位模式大小统一为1字节(8位),ASCII位模式通过在左边增加额外的0来进行扩充,使每一个模式都能很容易地恰好存入1字节大小的内存中。在扩展ASCII码中,第一个模式是00000000,最后一个是01111111。
(3)Unicode:为适应更大容量代码的需要,硬件和软件制造商们联合起来,共同设计了一种名为Unicode的代码,这种代码使用16位,能表示多达216=65536个符号。代码的不同部分被分配用于表示世界上不同语言的符号,其中还有部分代码被用于表示图形和特殊符号。Java语言就使用这种代码来表示字符。
微软公司的Windows使用了Unicode前256个字符的一个变化版本。
2.数
在计算机中,数是使用二进制系统,即位模式(一系列的0和1)来表示数。而像ASCII码这样的代码并没有用来表示数,这主要是因为数的表示方法不同于非数字形式的其他数据。
其他数据,如图形、图像和视频等的表示,将在本书第7章中进行详细介绍。
1.4.4 十六进制与八进制
数据存储在计算机中时是采用位模式表示的,但人们了解位模式时却很困难,一长串的0和1非常乏味且容易出错,这时,可以采用十六进制来加以简化。
十六进制以16为基数,这意味着有16个符号(十六进制数字),即0~9、A、B、C、D、E、F。十六进制数字与4个位对应,表1-1给出了位模式和十六进制数字间的关系。
将位模式转换成十六进制数,是将模式(从右边开始)组成每4个一组,找到与每组相对应的十六进制数字即可。例如,1111110011100100可表示成十六进制数的F C E 4。
表1-1 十六进制数字
十六进制有两种写法。
1)在数的前面加小写或大写的x来代表十六进制。例如,xA34表示一个十六进制数。
2)将数字基数(16)作为表示法的下标。例如,A3416表示一个十六进制的值。
例1将二进制数110011100010转换成十六进制数。
解 将该二进制数分成每4位—组,即:110011100010,再转换成对应的十六进制数字,最后得到的十六进制数为xCE2。
例2 将十六进制数x24C转换成位模式。
解 将每一个十六进制数字转换成相对应的位模式,最后得到的位模式为00100100 1100。
另一种简化位模式的分组表示法是八进制法。八进制法以8为基数,这意味着有8个符号(八进制数字),即0~7。每个八进制数字对应于3个位。在数的前面加小写或大写的o(oct,在希腊语中表示8)来代表当前的表示方法为八进制。例如,o12表示一个八进制数。
1.4.5 十进制与二进制
第一个使用十进制计数系统的是8世纪的古埃及人,巴比伦人则改进了埃及人使用的记数系统,使得位置在记数系统中变得有意义。
在现代计算机中,十进制和二进制这两种计数系统占主导地位。十进制系统数的幂为10,因此,第一位为100,第二位为101,第三位为102,等等。例如,十进制的243可分解为:2×102+4×101+3×100。
与十进制数为10不同,二进制系统数为2。例如,十进制数243转换为二进制数是11110011,同理可分解为:1×27+1×26+1×25+1×24+0×23+0×22+1×21+1×20。
1.二进制数向十进制数转换
给出一个二进制数,将其每个二进制数字分别乘以它的权值,再将结果相加,即得到相应的十进制数。
例1将二进制数10011转换成对应的十进制数。
解 写出每位上的数值和相应的权值,然后将每位上的数值和对应的权值相乘,最后将结果相加,即得到相应的十进制数。即
100112=1×24+0×23+0×22+1×21+1×20=1×16+0×8+0×4+1×2+1×1=1910
2.十进制数向二进制数转换
采用除2取余法。以十进制数45为例,被底数2连除,得二进制101101,如图1-15所示。
例2 将十进制数35转换成相对应的二进制数。
解 用除2取余法,如图1-16所示。
图1-15 十进制数45转换成二进制数
图1-16 十进制数35转换成二进制数
1.4.6 整数表示法
整数即没有小数部分的完整数。例如,134是整数,而134.23不是整数。整数可以是正数或负数。负整数的范围是从负无穷到0,正整数是从0到正无穷。
为了高效地利用计算机的存储空间,人们设计开发了两种使用广泛的整数表示法,即无符号整数和有符号整数。有符号整数最常用的表示法是二进制补码。
1.无符号整数格式
无符号整数的范围介于0到正无穷大之间。通常,计算机都定义一个最大无符号整数的常量。这样,无符号整数的范围就介于0到该常量之间。而最大无符号整数取决于不同计算机的存储能力。无符号整数的范围可定义为0~(2N-1),这里N就是计算机中分配用于表示一个无符号整数的二进制位数。
存储无符号整数的过程可以简单地概括为以下步骤。
1)首先将整数变成二进制数。
2)如果二进制位数不足N位,则在二进制数的左边补0,使它的总位数为N位。
例1 将7存储在8位存储单元中。
解 首先将这个数转换为二进制数111。在该二进制数的左边加5个0,使总的位数为N(8)位,即得到00000111。再将该数存储到计算机的存储单元中。
无符号整数表示法可以提高存储的效率,因为不必存储整数的符号。这就意味着所有分配的位单元都可以用来存储数。只要无须用到负数,都可以用无符号整数表示法。无符号数一般用在计数、寻址等情况下。
2.二进制补码格式
二进制补码表示法是最普遍、最重要,也是应用最广泛的整数表示法,其整数表示范围是:
-(2N-1)~+(2N-1-1)
这里,N是计算机分配用于存储二进制补码整数的位数。
表1-2给出了现代计算机整数表示的一般范围。系统中只有一个0。
表1-2 二进制补码数的范围
存储二进制补码需要以下步骤。
1)首先将数转换成二进制,符号被忽略。
2)如果二进制位数不足N位,在数的左边补0,直到总的位数为N。
3)如果符号为正,就不需再作变动。如果符号为负,则将最右边的所有0和首次出现的1保持不变,其余位取反。
在二进制补码表示法中,最左边的位定义为符号位。如果为0,数为正;如果是1,数为负。
例2 将+7用二进制补码表示法存储在8位存储单元中。
解 首先把数转换成二进制111,加上5个0使总的二进制位数为N(8)位,得到00000111。因为符号为正,不用再进行变化。
例3 将-40用二进制补码表示法存储在16位存储单元中。
解 首先把数转换成二进制101000,补上10个0使总的位数为N(16)位,得到0000000000101000。因为符号为负,所以,从右边的0到第一个l(包括1)不变,其余的换成它的反码形式。结果是:1111111111011000。
1.4.7 浮点数表示法
为了表示浮点数,数被分为两部分:整数部分和小数部分。例如,浮点数14.234就有整数部分14和小数部分0.234。
1.转换成二进制
把浮点数转换成二进制数,步骤如下。
1)把整数部分转换成二进制。
2)把小数部分转换成二进制。
3)在两部分之间加上小数点。
为把小数转换成二进制数,可以用连乘的方法,即“乘2取整法”。例如,把0.125转换成二进制数:将该数乘以2,得0.250,结果的整数部分(0)被提取出来,作为小数部分二进制数最左边的数字。接着继续用2来乘0.250得0.50。同样地,将结果的整数部分提取出来作为二进制数的下一位。如此反复,直到小数部分变成0或者达到你所能用到的位数。
例1 将小数0.875转换成二进制数。
解 将该数不断用2来乘,提取出整数部分作为二进制位。直到该数为0.0。得0.1112。
例2 将小数0.4转换成6位的二进制数(保留6位有效数字)。
解 将该数不断用2来乘,并提取出整数部分作为二进制位。在这个例子中,不可能恰好得到该小数正确的二进制表示,因为在乘的过程中原始小数再次出现,因此只需要取到题目所要求的6位就可以停止了。得0.0110012。
2.规范化
为了表示数71.3125(+1000111.0101),需要将符号、所有的位以及小数点的位置存储于内存中。这种方法虽然具有可行性,但使得数的运算变得困难。为此,需要浮点数标准表示法。解决的办法称为规范化,即移动小数点使小数点的左边只有一个“1”,即:
1.xxxxxxxxxxxxxxxxxx
为了表示这个数原始的值,将它乘以2e,这里e表示这个数的小数点所移动的位数:e为正数则左移,e为负数则右移。根据该数的正负将正负号加在最前面。表1-3给出了规范化的例子。
3.符号、幂和尾数
数在规范化之后只存储了这个数的三部分信息:符号、指数和尾数(小数点右边的位)。例如,+1000111.0101规范化后成为
表1-3 规范化示例
注意到小数点左边的l并没有存储,这种省略是可以理解的。
(1)符号。数的符号可以用一个二进制位来存储(0或者1)。
(2)指数。指数(2的幂)定义小数点移动的位数。幂可以为正也可以为负。
(3)尾数。尾数是指小数点右边的二进制数,它定义了数的精度。尾数作为无符号整数存储。