第2章 数的存储
第1节 机器数
计算机中,表示数和数的符号的二进制数,叫做机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1。
比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。那么,这里的 00000011 和 10000011 就是机器数。
机器数可用不同的码制来表示,常用的有原码、补码和反码表示法。
第2节 真值
因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。
例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1
第3节 有符号数处理
在计算机运算中,有符号数的表示需要将负数编码为二进制形式。在数学中,任意基数的负数都在最前面加上“?”符号来表示。然而在计算机硬件中,数字都以无符号的二进制形式表示,因此需要一种编码负号的方法。当前有四种方法,用于扩展二进制数字系统,来表示有符号数:原码(sign-and-magnitude),反码(ones‘ complement),补码(two‘s complement),以及移码excess-N。
1.原码
原码就是符号位加上真值的绝对值,符号及值(sign & magnitude)的处理法是分配一个符号位(sign bit)来表示这个符号:设置这个位(通常为最高有效位)为0表示一个正数,为1表示一个负数。数字中的其它位指示数值(或者绝对值)。因此一个字节只有7位(除去符号位),数值的范围从0000000(0)到1111111(127)。这样当你增加一个符号位(第八位)后,可以表示从?12710到+12710的数字。这种表示法导致的结果就是可以有两种方式表示零,00000000(0)与10000000(?0),这大大增加数码电路的复杂性和设计难度。CPU亦须执行两次比较,来测试运算结果是否为零。
十进制数?43用原码方法编码成八位的结果为10101011。
这种方法被直接比较于常用的符号表示法(放置一个“+”或者“?”在数字的数值之前)。一些早期的二进制电脑(例如IBM 7090)使用这种表示法,也许是由于它与通用用途的自然联系。原码是最常用的表示浮点数的方法。IEEE二进位浮点数算术标准(IEEE 754)采用最高有效位作为符号位,因此可表示正负零及正负无限。
2.反码
另一方面,一种叫做反码的系统也可以用于表示负数(注:正数与原码形式一样,无需取反)。一个负数的二进制数反码形式为其绝对值部分按位取反(即符号位不变,其余各位按位取反)。同原码表示一样,0的反码表示形式也有两种:00000000(+0)与11111111(?0)。
举例来说,原码10101011(-43)的反码形式为11010100(?43)。有符号数用反码表示的范围为?(2N?1?1)到(2N?1?1),以及+/?0。传统的表示为?12710到+12710,以及00000000(+0)或者11111111(?0)。
正数的反码是其本身, 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。注意负数的反码只需按位求数值的补就可以得到,符号不需要变动。
3.补码
补码(2‘s complement)是一种用二进制表示有号数的方法,也是一种将数字的正负号变号的方式,常在计算机科学中使用。在台湾和香港称为二补数。数据在计算机中主要是以补码的形式存储的。
一个数字的补码就是将该数字作比特反相运算(即一补数或反码),再将结果加 1。在补码系统中,一个负数就是用其对应正数的补码来表示。正数的补码就是其本身,负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1) 。
补码回避了0有多种表示的问题以及循环进位的需要。在补码表示中,负数以位模式表示为正值的反码加1(当作无符号数)。
在补码表示中,只有一个0(00000000)。求一个数的否(无论是负数还是正数)需要反转所有位,然后加1。一对补码整数相加等价于一对无符号数相加(除了溢出检测,如果能够做到的话)。比如,从旁边的表格可以看出,127与?128的补码表示相加就与无符号数127及128相加具有相同的结果。
补码系统的最大优点是可以在加法或减法处理中,不需因为数字的正负而使用不同的计算方式。只要一种加法电路就可以处理各种有号数加法,而且减法可以用一个数加上另一个数的补码来表示,因此只要有加法电路及补码电路即可完成各种有号数加法及减法,在电路设计上相当方便。
另外,补码系统的 0 只有一个表示方式,这点和一补数系统不同(在一补数系统中,0 有二种表示方式),因此在判断数字是否为 0 时,只要比较一次即可。
8-bit补码系统的整数。它的可表示的范围包括-128到127,总共256 (28)个整数。
以下用 4 比特的补码数字来说明补码系统的数字表示方式。
在表示正数和零时,二补数数字和一般二进制一样,唯一的不同是在补码系统中,正数的最高比特恒为 0,因此4 比特的补码正数,最大数字为 0111 (7)。
补码数字的负数,最高比特恒为 1,4 比特补码的数字中,最接近 0 的负数为 1111 (-1),以此类推,因此绝对值最大的负数是 1000 (-8)。
在一般 n 比特的二进制数字中,最高有效比特(MSB) 第 n 比特代表的数字为 2n?1。不过,在 n 比特的补码系统中,最高有效比特(MSB) 第 n 比特表示符号比特,若符号比特为 0,数字为正数或 0,若符号比特为 1,数字为负数。
求负数补码表示的方法:
(1)写出与该负数相对应的正数的补码
(2)按位求反
(3)末位加一
例:假设机器字长为8位,求-46的补码。
+ 46的补码表示为: 0010 1110
按位求反: 1101 0001
末位加一 1101 0010
所以,[-46]补码 = D2H
符号扩展:是指一个数从位数较少扩展到位数较多,如从8位扩展到16位,或从16位扩展到32位。
对于用补码表示的数,正数的符号扩展在前面补0,负数的符号扩展在前面补1,假设机器字长为16位,[+46]补码 = 002EH,[-46]补码 = FFD2H。
n位补码的表数范围
8位二进制数可以表示=256个数,16位二进制数可以表示=65536个数,当它们是补码表示的带符号数时,8位二进制的表数范围是 -128 N +127,
16位二进制的表数范围是 -32768 N +32767。
n位补码的表数范围是:
4.移码
移码,是将二进制原码无符号整数所代表的值,减去一个预设值。
标准移码,预设值为二进制原码表示的最大整数的一半。 一个数的标准移码和补码,最高位相反,其余各位均相同。
#include <stdio.h>
int main(int argc, char * argv) {
char a;
short b;
a = 127;
b = (short)127;
printf("a=%08X,b=%d.\n", a, b);
a = 128;
b = (short)128;
printf("a=%08X,b=%d.\n", a, b);
a = 1;
b = (short)1;
printf("a=%08X,b=%d.\n", a, b);
a = 0;
b = (short)0;
printf("a=%08X,b=%d.\n", a, b);
a = -0;
b = (short)-0;
printf("a=%08X,b=%d.\n", a, b);
a = -1;
b = (short)-1;
printf("a=%08X,b=%d.\n", a, b);
a = -128;
b = (short)-128;
printf("a=%08X,b=%d.\n", a, b);
a = (char) -129;
b = (short)-129;
printf("a=%08X,b=%d.\n", a, b);
return 0;
}
a=0000007F,b=127.
a=FFFFFF80,b=128.
a=00000001,b=1.
a=00000000,b=0.
a=00000000,b=0.
a=FFFFFFFF,b=-1.
a=FFFFFF80,b=-128.
a=0000007F,b=-129.
补码的加、减法
对一个二进制数按位求反、末位加一的运算称为求补运算,补码表示的数具有以下特征:
补码的加法规则是:[X+Y]补=[X] 补+[Y] 补
补码的减法规则是:[X-Y] 补=[X] 补+[-Y] 补
其中通过对求补就可以得到。
在机器里,补码减法是通过对减数求补后把减法转换为加法进行的。符号位参加运算,能自动得到正确结果。
例:假设机器字长为8位,计算25+(-32)
25的补码是0001 1001,-32的补码是1110 0000,
结果恰好是-7的补码1111 1001,可以看出运算是正确的。
例:仍假定机器字长为8位,计算32-(-25)
为把减法转换为加法,要对-25求补,实际上就是25的补码0001 1001, 32的补码是0010 0000,
结果恰好是57的补码0101 0111,运算正确。
在某些情况下,要处理的数全是正数(比如表示地址的数),就没有必要保留符号位了,可以把最高有效位也作为数值处理,这样的数称为无符号数。n位无符号数的表数范围是。
第4节 BCD码
二进码十进数(英语:Binary-Coded Decimal,简称BCD,台湾称二进码十进数)是一种十进制的数字编码形式。这种编码下的每个十进制数字用一串单独的二进制位元来储存表示。常见的有4位元表示1个十进制数字,称为压缩的BCD码(compressed or packed);或者8位元表示1个十进制数字,称为未压缩的BCD码(uncompressed or zoned)。
这种编码技术,最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。
BCD码的主要优点是在机器格式与人可读的格式之间转换容易,以及十进制数值的高精度表示。BCD码的主要缺点是增加了实现算术运算的电路的复杂度,以及存储效率低。
常用BCD编码方式
最常用的BCD编码,就是使用"0"至"9"这十个数值的二进码来表示。这种编码方式,称为8421BCD, 除此以外,对应不同需求,各人亦开发了不同的编码方法,以适应不同的需求。这些编码,大致可以分成有权码和无权码两种:
1.有权码,如:8421(最常用)、2421、5421…
2.无权码,如:余3码、格雷码…
1.8421BCD编码
这是一种使用最广的BCD码,是一种有权码,其各位的权分别是(从最有效高位开始到最低有效位)8、4、2、1(即23、22、21、20),因而称为“8421BCD编码”。
比如:8421BCD码的1011=8*1+4*0+2*1+1*1=11
在使用8421BCD码时一定要注意其有效的编码仅十个,即:0000~1001。4位二进制数的其余6个编码1010、1011、1100、1101、1110、1111不是有效编码。这种BCD编码实际上就是0~9的“等值”二进制数。
2.2421BCD编码
2421BCD码也是一种有权码,其从高位到低位的权分别为2、4、2、1(同样也是它得名的原因),其也可以用4位二进制数来表示1位十进制数。
比如: 2421BCD码的(1100 0100 0010)=十进制的(6 4 2)
因为
2421BCD码的1100=2*1+4*1+2*0+1*0=6
2421BCD码的0100=2*0+4*1+2*0+1*0=4
2421BCD码的0010=2*0+4*0+2*1+1*0=2
3.余3码
余3码也是一种BCD码,但它是无权码。但由于每一个码对应的8421BCD码之间相差3,故称为余3码,其一般使用较少,故只须作一般性了解。
余三码是在8421BCD码的基础上,把每个数的代码加上0011(对应十进制数3)后得到的。
4.格雷码
格雷码(循环二进制单位距离码)是任意两个相邻数的代码只有一位二进制数不同的编码,它与奇偶校验码同属可靠性编码。
格雷码(Gray code)是由贝尔实验室的Frank Gray在1940年提出,用于在PCM(脉冲编码调变)方法传送讯号时防止出错,并于1953年3月17日取得美国专利。格雷码是一个数列集合,相邻两数间只有一个位元改变,为无权数码,且格雷码的顺序不是唯一的。
格雷码能避免讯号传送错误的原理
传统的二进位系统例如数字3的表示法为011,要切换为邻近的数字4,也就是100时,装置中的三个位元都得要转换,因此于未完全转换的过程时装置会经历短暂的,010,001,101,110,111等其中数种状态,也就是代表着2、1、5、6、7,因此此种数字编码方法于邻近数字转换时有比较大的误差可能范围。葛雷码的发明即是用来将误差之可能性缩减至最小,编码的方式定义为每个邻近数字都只相差一个位元,因此也称为最小差异码,可以使装置做数字步进时只更动最少的位元数以提高稳定性。 数字0~7的编码比较如下:
十进位 葛雷码 二进位
0 000 000
1 001 001
2 011 010
3 010 011
4 110 100
5 111 101
6 101 110
7 100 111
直接排列
以二进制为0值的格雷码为第0项,第1项改变最右边的位元,第2项改变右起第一个为1的位元的左边位元,第3、4项方法同第1、2项,如此反复,即可排列出n个位元的格雷码。
格雷码转二进位数
二进位码第n位 = 二进位码第(n+1)位+格雷码第n位。因为二进位码和格雷码皆有相同位数,所以二进位码可从最高位的左边位元取0,以进行计算。(注:遇到1+1时结果视为0)
例如: 格雷码0111,为4位数,所以其所转为之二进位码也必为4位数,因此可取转成之二进位码第五位为0,即0 b3 b2 b1 b0。
0+0=0,所以b3=0
0+1=1,所以b2=1
1+1=10取0,所以b1=0
0+1=1,所以b0=1
因此所转换为之二进位码为0101
应用
格雷氏编码与相位移在三维曲面量测:利用格雷码投射在微型曲面做量测 一个非接触式、投影的方法光学测量。在化简逻辑函数时,可以通过按格雷码排列的卡诺图来完成。
和葛雷码有相同数学模式的玩具
中国的古老益智玩具九连环有着和格雷码完全相同的数学模式,外国一款名为spin out的玩具也是运用相同的数学模式。