计算机发明的初衷就是用于帮助我们加工和处理数据,虽然时至今天计算机看起来无所不能,但它根本上还是在做数据的加工和处理,数据的机器层次表示将直接影响到计算机的结构和性能。
在计算机中,采用数字化方式来表示数据,数据有无符号数和带符号数之分,其中带符号数根据其编码的不同又有原码、补码和反码3中表示形式。下面我们来认识一下;
无符号数和带符号数
所谓无符号数,就是整个机器字长的全部二进制位均表示数值位(没有符号位),相当于数的绝对值,大致相当于数学中的自然数。如01000001表示无符号数65,11000001表示无符号数193。机器字长为n+1位的无符号数的表示范围是0 ~(2^(n+1) - 1),此时二进制的最高位也是数值位,其权值等于2^n。如字长为8,那么数的表示范围就是0~255。一般计算机中都会有一些无符号数的运算和处理指令,如条件转移指令等。
然而,如同我们现实世界所见的大部分数据一样,它还是需要区分正负(“+”“-”)的。在日常生活中我们使用正负和绝对值来表示数值的大小,用这种形式表示的数值在计算机技术中称为“真值”。
对于数的符号“+”和“-”,计算机是无法识别的(实际上除了0和1,计算机什么也识别不了),因此需要把符号数码化。通常约定二进制数的最高位为符号位,“0”表示正号,“1”表示负号。这种在计算机中使用的表示数的形式称为机器数,常见的机器数有原码、反码和补码等不同的表现形式。
区别于无符号数,带符号数的最高位被用来表示符号,如上面的01000001表示带符号数为正65,11000001表示带符号数为-65。为了能正确的区别出真值和各种机器数,我们用X表示真值,[X]原表示原码,[X]补表示补码,[X]反表示反码。原码、补码和反码是计算机中的几种表现形式,目的在于能够使计算机对数据的一系列运算得出正确结果。
原码表示法
原码表示法是一种最简单的机器数据表示法,其最高位是符号位,数值部分则与真值相同。
若真值是纯小数,那么原码的定义为:
[X]原 = X 0<=X<1
[X]原 = 1-X = 1+|X| -1<X<=0
若真值为纯整数,它的原码定义为:
[X]原 = X 0<=X<2^n
[X]原 = 2^n-X = 2^n + |X| -2^n<X<=0
因为原码具有符号位,所以原码中的0是有两种表示形式的
[+0]原 = 00000
[-0]原 = 10000
原码表示法的优点是直观易懂,机器数和真值间的相互转换很容易,用原码实现乘除运算阿德规则很简单;缺点则是实现加减运算的规则较为复杂.
补码表示法
在介绍补码之前,先认识一下模和同余。
模和同余
我们这里所说的模和通常所见的模数是不同的概念,这里所说的模(Module)是指一个计量器的容量,可用M表示。例如:一个4位的二进制计数器,当计数器从0开始计数到15之后,再加1,计数器的值就又会变成0。这个计数器的容量M = 2^4 = 16,即模为16。由此可见,纯小数的模为2(二进制计数中对于纯小数,它们的模永远都是2,因为一旦小数位全为1后就会进位位整数位,所以小数位的周期都是2,即模数(容量)为2。),一个字长为n+1位的纯整数的模为2^(n+1)。
同余概念是指两个整数A和B除以同一个正整数M,所得余数相同,则称A和B对M同余,即A和B在以M为模时是相等的,可写作
A = B(mod M)
生活中最常见的同余莫过于时钟了,对于时钟而言,其模M = 12,故4点和16点、5点和17点、……均是同余的,它们可以写作
4 = 16(mod 12) 5 = 17(mod 12)
利用模和同余概念的补码表示法在进行算术运算时可以使减法运算转化成加法运算,从而简化机器的运算器电路。
还以时钟为例,假如时钟停留在8点,而现在正确的时间是6点,这时拨准时种的方法有两种:
- l 将分针倒着拨两圈(即倒拨两小时)8-2=6(这是通过减法实现的)。
- l 将分针正着旋转10周(即正拨10小时)8+10=6(mod 12)(这是通过加法实现的)
此时 8 - 2 = 8 + 10(mod 12)
设:A = -2 , B = 10
则:10/12 = (12-2)/12 = 1 + (-2/12)
上面-2和10也是同余。同余的两个数具有互补的关系,-2和10对模12互补,也就是说-2的补数是10(以12位模)。
由此可见,只要确定了“模”,就可找到一个与负数等价的正数(该正数即为负数的补数)来代替此负数,而这个正数可以用模加上负数本身求得,这样就可把减法运算转换为加法运算实现了。而将补数概念运用到计算机中就出现了补码这种机器数。
[X]补 = X (mod M) 0 <= X < M/2
[X]补 = (M + X)(mod M) (-M/2) <= X < 0
补码表示
补码的符号位表示方法和原码相同,其数值部分的表示与数的正负有关:对于正数其数值部分与真值形式相同;对于负数,将真值的数值部分按位取反,且在最低位上加1。
若真值为纯小数,它的补码表示为:
[X]补 = X (mod 2) 0 <= X < 1
[X]补 = (2 + X)(mod 2) = (2-|X|)(mod 2) -1 <= X < 0
若真值是纯整数,它的补码为:
[X]补 = X 0<=X<2^n
[X]补 = X + 2^(n+1) = 2^(n+1) - |X| -2^n<X<=0
在补码表示中,0的表示形式是唯一的:
[+0]补 = [-0]补 = 00000
反码表示法
反码表示法与补码表示法有许多类似之处,对于正数,数值部分与真值形式相同;对于负数,将真值的数值部分按位取反。它与补码的区别是末位少加一个1,因而很容易从补码的定义推出反码的定义。
三种机器数的比较与转换
通过上面的学习,我们知道数值在计算机中的三种表现形式,下面我们针对这三种数据进行比较学习;
比较
原码、反码、补码这三种机器数既有共同点,又有各自不同的性质,主要区别有一下几点:
- l 对于正数它们都等于真值本身,对于负数有各自的表现形式。
- l 最高位都用来表示符号位,补码和反码的符号位可作为数值位的一部分看待,和数值一起参与运算;但原码的符号位不允许和数值位同等看待,必须分开处理。
- l 对于真值0,原码和反码各有两种不同的表现形式,而补码只有唯一的表现形式。
- l 原码、反码表示的正负数范围相对零来说是对称的;但补码负数表示范围较正数表示范围宽,能多表示一个最负的数(绝对值最大的负数),其值等于-2^n(纯整数)或-1(纯小数)。