程序设计教程:用C++语言编程(第4版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.1.3 机内信息表示

在计算机的内部,任何信息(指令、数据和地址)都是用“0”和“1”组成的二进制数字序列来表示的。计算机内部之所以采用二进制来表示信息,是因为“0”和“1”分别对应着电气设备的两个稳定状态,如开关的关/开、电压的低/高、电流的小/大等。

对于基于“0”和“1”表示的信息,其常用的计量单位有:

•二进制位(bit,简写成b):由一个“0”或“1”构成。

•字节(byte,简写成B):由8个二进制位构成。

•千字节(kilobyte,简写成KB):由1024个字节构成。

•兆字节(megabyte,简写成MB):由1024个千字节构成。

•吉字节(gigabyte,简写成GB):由1024个兆字节构成。

•太字节(terabyte,简写成TB):由1024个吉字节构成。

……

在内存与外存中,通常把字节作为基本存储单位(每次存取至少为一个字节)。内存与外存的容量常常也是以字节数来计算的。例如,内存的容量通常为2GB、4GB、8GB等,硬盘的容量通常为320GB、500GB、1TB等。

在计算机的信息表示中,数据的表示占有很重要的地位。在日常生活中,数一般采用十进制来表示,而在计算机中,数则是以二进制来表示的。下面先简单介绍数的几种常见进制表示以及它们之间的转换规则,然后介绍整数和实数在计算机内部的二进制表示方法。

1.数的几种进制表示

数的常见进制表示有十进制、二进制、八进制和十六进制。表1-1给出了一些数的几种进制表示,它们有以下特征:

•十进制(decimal):由0~9组成,计数时逢十进一。

•二进制(binary):由0~1组成,计数时逢二进一。

•八进制(octal):由0~7组成,计数时逢八进一。

•十六进制(hexadecimal):由0~9以及A~F组成,计数时逢十六进一。

表1-1 一些数的几种进制表示

例如,对于十进制数13,它的二进制表示为1101,八进制表示为15,十六进制表示为D。再例如,对于十进制数13加上3,与它对应的各种进制数的加法运算如下:

数的各种进制之间是可以相互转换的。下面简单介绍各种进制数之间的转换。

2.十进制与其他进制之间的转换

(1)十进制转换成二进制

对于一个十进制数的整数部分,可以把它连续除以基数2,直到商为0,所得的各个余数的倒序即为对应的二进制数。例如,对于十进制整数29,其二进制表示的计算过程如图1-4所示(结果为11101)。

对于一个十进制数的小数部分,可以把它连续乘以基数2,每次去掉乘积的整数位,直到乘积只包含整数为止,最后的转换结果由各个乘积的整数位构成。例如,对于十进制小数0.8125,其二进制表示的计算过程如图1-5所示(结果为0.1101)。需要注意的是,有些十进制小数是无法精确转换成二进制小数的。例如,十进制小数0.1转换成二进制是多少呢?(请读者自己算一算。)

图1-4 十进制整数转换为二进制整数的过程

图1-5 十进制小数转换为二进制小数的过程

(2)二进制转换成十进制

对于一个二进制数的整数部分,可以把它的各位分别乘以基数2的相应正数(包括零)次幂,然后求和。例如:

(11101)2=1×24+1×23+1×22+0×21+1×20=(29)10

对于一个二进制数的小数部分,可以把它的各位分别乘以基数2的相应负数次幂,然后求和。例如:

(0.1101)2=1×2-1+1×2-2+0×2-3+1×2-4=(0.8125)10

(3)十进制与八进制和十六进制之间的转换

对于十进制与八进制和十六进制之间的转换,其转换过程与上述的十进制与二进制之间的转换类似,只要把上面的基数2改为8或16即可。除此之外,还可以通过二进制来实现十进制与八进制和十六进制之间的转换。

3.二进制与八进制、十六进制之间的转换

二进制与八进制、十六进制之间的转换相对简单。当把二进制转换成八进制时,只要以小数点为中心,分别向左和向右按3位一组划分,不足3位的,整数部分在左补“0”,小数部分在右补“0”,然后把每一组分别转换成八进制。例如:

反过来,当把八进制转换成二进制时,只要把每一个八进制位转成3位二进制数,最后去掉多余的“0”即可。例如:

同理,当把二进制转换成十六进制时,只要以小数点为中心,分别向左和向右按4位一组划分,不足4位的,整数部分在左补“0”,小数部分在右补“0”,然后把每一组分别转换成十六进制。例如:

反过来,当把十六进制转换成二进制时,只要把每一个十六进制位转成4位二进制数,最后去掉多余的“0”即可。例如:

4.整数和实数的机内表示

在计算机中,数虽然是以二进制来表示和存储的,但具体表示形式和存储方式通常会根据计算机的特点来设计。下面分别介绍整数和实数的常见机内表示方法。

(1)整数的原码表示

整数的一种机内表示方法是采用固定长度的二进制原码来表示,即用一个二进制位(通常为最高位)表示它的正负号(0表示正,1表示负),用其他二进制位表示它的绝对值。例如,如果用一个字节存储整数,则12和-12的原码分别为00001100和10001100。对于由n个二进制位构成的原码,它能表示的整数范围是-(2n-1-1)~2n-1-1。其中,01…1表示最大的正整数,11…1表示最小的负整数,零有两个,即00…0(正零)和10…0(负零)。

(2)整数的补码表示

整数的另一种机内表示方法是采用固定长度的2的补码(2's complement)来表示。正整数的补码为它的二进制原码,负整数的补码为把与之对应的正整数的补码表示中各个二进制位分别取反后得到的二进制数加1。例如,如果用一个字节存储整数,则12和-12的补码分别为00001100和11110100。需要注意的是,在整数的补码表示中,负整数的补码最高位虽然也是1,但其余的二进制位不是它的绝对值。另外,对于负整数的补码,把其各个二进制位分别取反后加1则能得到对应正整数的补码。对于由n个二进制位构成的补码,它能表示的整数范围是-2n-1~2n-1-1。其中,01…1表示最大的正整数,10…0表示最小的负整数,零只有一个,即0…0,没有负零。

用补码表示整数的好处是可以简化加减运算,特别是减法可以转换成加法来做。对于加法,两个数的补码直接相加,舍去最高位的进位;对于减法,只要把减数取负(可以通过把它的各个二进制位分别取反后加1得到),然后与被减数相加即可。例如,对于用一个字节表示的整数,5加-2的计算过程如下:

再例如,对于2减8,则可以按2加-8计算:

现代计算机CPU的整数运算指令一般是针对2的补码表示来设计的。

(3)实数的浮点表示

实数在计算机内部一般采用固定长度的基于科学记数法的二进制形式来表示,即把实数表示成a×2b。其中,a是一个固定长度的二进制小数,称为尾数(mantissa);b是一个固定长度的二进制整数,称为阶码或指数(exponent)。在计算机内部,实数存储的是它的符号、尾数和指数三个部分,并且在存储实数前,首先需要对其进行规格化,即把尾数调整为1.xxx...形式,其中的整数位“1”和小数点不存储。由于在实数的这种表示中,小数点的位置并不表示它的实际位置,其真正位置是“浮动”着的,要由尾数和指数共同来决定,因此,在计算机中实数常常又称为浮点数(float-point number)。关于浮点数的具体机内表示可参见附录B。需要注意的是,对于一些实数(如0.1),浮点表示法是不能精确表示它们的!

现代计算机CPU的实数运算指令一般是针对实数的浮点表示来设计的。

(4)实数的BCD码表示

对于实数,在计算机内还常采用另一种二进制表示法,即BCD码(binary coded decimal code),它对十进制数的每一位分别用一个二进制码来表示。BCD码有多种形式,常用的是8421码,它用四位二进制来表示十进制数的一位数字,其范围是0000~1001,分别对应着十进制数字0~9。例如,表1-2给出了一些十进制数的BCD码表示。

表1-2 一些十进制数的BCD码表示

在十进制数的BCD码表示中,可用不允许在BCD码中出现的六个编码(1010、1011、1100、1101、1110和1111)中的三个来分别表示小数点、正号和负号。例如,如果用1010表示正号,用1011表示负号,1111表示小数点,则-123.4可表示成1011 0001 0010 0011 1111 0100。BCD码的长度是不固定的,为了节省存储空间,常常采用压缩形式来存储BCD码,即用一个字节存放两个BCD码。

BCD码表示的好处是能用二进制来精确表示十进制小数并能表示长度较长的十进制数,它的不足之处在于,CPU指令一般不能直接对BCD码表示的数进行操作,它需要通过若干条指令(一段程序)来实现。