本章重点讨论计算机内部数据的机器级表示方式,包括进位计数制、二进制定点数的编码表示、无符号整数和带符号整数的表示、IEEE 754浮点数表示标准、西文字符和汉字的编码表示、十进制数的二进制编码表示(即BCD)、C语言中各类数据类型的表示和转换、数据宽度和存放顺序以及几种常用检/纠错码的编码表示与使用方法。
数制和编码
数据信息的二进制编码
在计算机内部,所有信息都用二进制数字表示。这是因为:
二进制只有2种基本状态,而使用有2个稳定状态的物理器件可以容易地表示二进制数的每一位
二进制的编码、计数和运算规则都很简单,可以用开关电路实现,简单易行
2个符号’1‘和’0‘正好与逻辑命题的2个值’真‘和’假‘相对应,为计算机中实现逻辑运算和程序中的逻辑判断提供了便利条件,特别是通过逻辑门电路方便地实现算术运算
指令所处理的基本数据类型分为2种:
数值类型:可用来表示数量的多少,可比较其大小,分为整数和实数,整数又分为无符号整数和有符号整数,在计算机内整数用定点数表示,实数用浮点数表示
非数值类型:不表示数量的多少,主要包括字符数据和逻辑数据
日常生活中,常使用带正负号的十进制数表示数值数据。但是,在计算机内部,数值数据通常使用二进制数表示。如果采用十进制数表示数据的话,也要将十进制数编码译成二进制数,即采用二进制编码的十进制数(Binary Coded Decimal Number,简称BCD)表示。
表示一个数值数据要确定三个要素:进位计数制,定/浮点表示和编码规则。任何给定的一个二进制0/1序列,在未确定它采用什么进位制、定点还是浮点表示以及编码表示方法之前,它所代表的数值数据的值是无法确定的。
进位计数制
一般用B(Binary)表示二进制、O(Octal)表示八进制、D(Decimal)表示十进制、H(Hexadecimal)表示十六进制
十进制数(日常生活中常用)
基数:10 (0、1、2、3、4、5、6、7、8、9) 代表每个数位上可以使用的不同数字符号的个数。
权:不同位上相同的基数所代表的数值不同,10i称为第i位上的权,基数的i次幂即为i位的权
进位规则:逢十进一
二进制数
基数:2 (0\1)
权:2i称为第i位上的权
进位规则:逢二进一
八进制数
基数:8 (0、1、2、3、4、5、6、7、8)
权:8i称为第i位上的权
进位规则:逢八进一
十六进制数
基数:16 (0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F)
权:16i称为第i位上的权
进位规则:逢十六进一
计算机在数据输入之后或输出之前都必须实现这些计数制和二进制数之间的转换。
R进制数转换成十进制数,只要按权展开即可
十进制数转换成R进制数,要将整数和小数部分分别进行转换
整数部分转换:除基取余,上右下左,用要转换的十进制整数去除以基数R,将得到的余数作为结果中各位的数字,直到余数为0。上面的余数作为右边低位上的数位,下面的余数左右左边高位上的数位
十进制数135转换成二进制和八进制
小数部分转换:乘基取整,上左下右,用要转换的十进制小数去乘以基数R,将得到的乘积的整数部分作为结果数据中的各位的数字,小数部分继续与基数R相乘,直到某一步乘积的小数为0或已得到希望的位数为止。上面的整数部分作为左边高位上的数位,下面的整数部分作为右边地位上的数位
十进制数0.6875转换成二进制和八进制
含整数和小数部分的数的转换:将整数部分和小数部分分别转换,再将两部分组合起来得到一个完整的数
二、八、十六进制数的转换
八进制数和二进制数的转换:把每个八进制数字改写为等值的3位二进制数即可,且保持高低位的次序不变
十六进制数和二进制数的转换:把每个十六进制数字改写位等值的4位二进制数即可,且保持高低位的次序不变
定点数的编码表示
定点数的编码表示主要有以下4种,原码、补码、反码和移码。通常将数值数据在计算机内部编码表示的数称为机器数,而机器数真正的值称为机器数的真值。
注意:以下各种表示方法都是在8位计算机中的原码表示,如果在32位或16位计算机中,表示方法是一样的,只是多了几个0而已.
原码表示法
一个数的原码表示由符号位也叫数符(左边第一位,也可以说是最高位,0表示正数,1表示负数)直接跟数值部分(数的绝对值)为构成,因此,也称“符号-数值”(sign and magnitude)表示法。正数和负数的编码表示仅符号位不同,数值部分完全相同。
原码编码规则如下:
当XT为正数时,Xn-1 = 0, Xi=X'i (0<=i<=n-2)
当XT为负数时,Xn-1=1,Xi=X'i (0<=i<=n-2)
原码0有两种表示形式:
优点:与真值的对应关系直观、方便,因此与真值的转换简单
缺点:零的表示不唯一,给使用带来不便,并且原码加/减运算规则复杂。在进行原码加减法运算过程中,要判断是否是两个异号数相加或同号数进行加减,若是,则必须判定两个数的绝对值大小,根据判断结果决定结果符号,并用绝对值大的数减去小的数。
+1+-1=0,但计算机只能算出0000 0001+1000 0001=1000 0010 = (-2) 这不是我们想要的结果
而且这里还有一个+0和-0
现代计算机中不用原码来表示整数,只使用原码小数来表示浮点数的尾数部分
补码表示法
一个数的补码表示由符号位跟上真值的模2n补码构成,补码表示法也称为“2-补码”(two's complement)表示法
模运算:在模运算系统中,若A,B,M满足下列关系:A=B+KM(K为整数)则记为A≡B(mod M)。即A、B各除以M后的余数相同,故称B和A为模M同余。也就是说一个模运算系统中,一个数与它除以“模”后得到的余数是等价的。5 = 1 + 2 * 2, 5对2模运算和1对2模运算得到的值是相同的。
钟表是一个很典型的模运算系统,其模数为12,假设现在时间是10点,要将它拨到6点,则有两种拨法:
顺时针拨动8小时 10+8 = 18≡6(mod 12)
逆时针波动4小时 10-4 = 6
所以在模12系统中,10-4≡10+(12-4)≡10+8(mod 12),即:-4≡8(mod 12),我们乘8是-4对模12的补码。同样有-3≡9(mod 12)等
得出的结论:对于某一个确定的模,某数A减去小于模的另一个数B,可以用A加上-B的补码来替代。这就是为什么补码可以借助加法运算来实现减法运算的道理。
溢出:计算机中的存储、运算和传递部件都只有有限位,也就是说长度是固定的。但两个n位二进制数在进行运算过程中,可能会产生一个多于n位的数,此时,就只能舍弃高位而仅保留低n位,这样做可能产生两种结果:
剩下的低n位数不能正确的表示运算结果,也即丢掉了的高位是计算结果的一部分。我们称此时发生了”溢出(overflow)“现象。
剩下的低n位数可以正确的表示运算结果,也即高位的舍去并不影响其运算结果。在两个同号数相减或两个异号数相加时,舍去高位的操作相当于”将一个多于n位的数去除以2n,保留其余数作为结果”的操作,也就是“模运算”操作
根据同余概念和数的互补关系,可以得出补码表示方法:正数的补码就是它本身;负数的补码等于模与该负数绝对值之差。
数XT的补码编码规则如下
当XT为正数时:[XT]补 = XT = M+XT (mod M)
当XT为负数时:[XT]补=M-|XT|= M+XT (mod M)
[XT]补 = 2n + XT (-2n-1 <= XT <2n-1, mod 2n)
n位补码的最大可表示值为+(nn-1 -1),最小值为-2n-1
优点:
可以实现加减运算的统一,即用加法来实现减法运算。
去除了-0的存在,减少了+0和-0之间的转换;增加了一个最小负整数-2n-1。位数为8时,带符号整数范围:-128~127
求负数补码的方法
方法一:变反加1法,即符号位不变,其余位变反,末位加1
方法二:搜索法,从低位向高位搜索,遇到非0停止,符号位不变,高位取反,末尾不变
方法三:按定义求,适合于求边界值的补码
求补码求原码于真值
正数:补码就是原码
负数:再次求补码,就是原码
反码
负数的补码可采用“各位求反,末位加1”的方法得到,如果仅各位求反而末位不加1,那么就可以得到负数的反码表示,因此负数反码的定义就是在响应的补码表示中末位减1。
反码表示存在以下几个方面的不足:
0的表示不唯一
表数范围比补码少一个最小负数;运算时必须考虑循环进位。因而,反码在计算机中很少使用,有时用作数码变换的中间表示形式。
移码
用浮点数表示一个数值数据时,实际上是用这两定点数来表示:用一个定点小数表示浮点数的尾数,用一个定点整数表示浮点数的阶(指数)。一般情况下,浮点数的阶都用一种称为移码的编码方式表示。为避免混淆,将阶的移码称为阶码,因此阶指的是真值,而阶码指的是机器数。
阶E可以是正数,也可以是负数,当进行浮点数的加减运算时,必须先对阶(即比较两个数阶的大小并使之相等)。为简化比较操作,是操作过程不涉及阶的符号,可以对每个阶都加上一个正的常数,称为偏置常数,使所有阶都转换为整数,这样,在对浮点数的阶进行比较时,就是对两个正整数进行比较,因而可以直观的将两个数按位从左到右进行比较,简化了对阶操作。
假设用来表示阶的移码的位数位n,则[E]移=偏置常数+E。通常,偏置常数取2n-1或2n-1-1。