计算机中为例子于存储及计算的物理实现,采用二进制数。二进制数的基数为2,只有0,1两个数码,并遵循逢2进1的规则,它的各位权是以2 k 表示的,因此二进制数anan-1…a0·b1b2…bm的值是:
an·2n + an-1·2n-1 + … + a0·20 + b1·2-1 + b2·2-2 + … + bm·2-m
其中ai,bj为0,1两个数码中的一个。例如:
1011012 =1×25+1×23+1×22+1×20=4510
其中数的下标表示该数的基数r,即二进制的101101与十进制的45等值。
n位二进制数可以表示2n个数。例如3位二进制数可以表示8个数,而4位二进制数则表示十进制的0~15共16个数。
为便于人们阅读及书写,经常使用八进制或十六进制数来表示二进制数。它们的基数和数码如下所示:
十六进制数,基数为16,数码:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
十进制数,基数为10,数码:0,1,2,3,4,5,6,7,8,9
八进制数,基数为8,数码:0,1,2,3,4,5,6,7
二进制数,基数为2,数码:0,1
在计算机里,通常用数字后面跟一个英文字母来表示该数的数制。十进制数一般用D(decimal)、二进制数用B(binary)、八进制数用O(octal)、十六进制数用H(hexadecimal)来表示。例如:117D,1110101B,0075H,…。也可以用这些字母的小写形式来表示。
1. 二进制数转换为十进制数
各位二进数码乘以与其对应的权之和即为该二进数相对应的十进制数。例如:
1011100.10111B=26+24+23+22+2-1+2-3+2-4+2-5=92.71875D
2. 十进制数转换为二进制数
十进制数转换为二进制数的方法很多,这里只说明比较简单的降幂法及除法两种。
(1)降幂法
首先写出要转换的十进制数,其次写出所有小于此数的各位二进制权值,然后用要转换的十进制数减去它最相近的二进制权值,如够减,则减去并在相应位记以1;如不够减,则在相应位记以0并跳过此位;如此不断反复,直到该数为0为止。
例1.1 N=117D,小于N的二进制权为:
64 32 16 8 4 2 1
对应的二进制数是 1 1 1 0 1 0 1
计算过程如下:
117-26 = 117 – 64 =53 (a6=1)
53-25 = 53 – 32 = 21 (a5=1)
21-24 = 21 – 16 =5 (a4=1)
(a3=0)
5-22 =5 - 4 = 1 (a2=1)
(a1=0)
1-20 = 1-1 = 0 (a0=1)
所以N=117D=1110101B。
例1.2 N=0.8125D,小于此数的二进数权为:
0.5 0.25 0.125 0.0625
对应的二进制数是:1 1 0 1
计算过程如下:
0.8125-2-1=0.8125-0.5=0.3125 (b1=1)
0.3125-2-2=0.3125-0.25=0.0625 (b2=1)
(b3=0)
0.0625-2-4=0.0625-0.0625=0 (b4=1)
所以N=0.8125D=0.1101B。
(2)除法
例1.3 N=117D
117/2=58 (a0=1)
58/2=19 (a1=0)
29/2=14 (a2=1)
14/2=7 (a3=0)
7/2=3 (a4=1)
3/2=1 (a5=1)
1/2=0 (a6=1)
所以N=117D=1110101B。
对于被转换的十进制数的小数部分则应不断乘以2,并记下其整数部分,直到结果的小数部分为0为止。
例1.4 N= 0.8125D
0.8125 × 2 = 1.625 (b1 = 1)
0.625 × 2 = 1.25 (b2 = 1)
0.25 × 2 = 0.5 (b3 = 0)
0.5 × 2 = 1.0 (b4 = 1)
所以N = 0.8125D = 0.1101B。
我们知道,在计算机内部,数的运算和存储都是采用二进制的。但是,二进制数对于人的阅读,书写及记忆都是很不方便的。十进制数虽然是人们最熟悉的一种进位记数制,但它与二进制数之间并无直接的对应关系。为了便于人们对二进制数的描述,应该选择一种易于与二进制数相互转换的数制。显然,使用2n 作为基数的数制是能适合人们的这种要求的,常用的有八进制数和十六进制数。
1. 十六进制数的表示
计算机中存储信息的基本单位为一个二进制位(bit),它可以用来表示0和1两个数码。此外,由于计算机中常用的字符是采用由8位二进制数组成的一个字节(byte)来表示的,因此字节也成为计算机中存储信息的单位。计算机的字长一般都选项为字节的整数倍,如16位、32位、64位等。一个字由8位组成,它可以用两个4位组(又称半字节)来表示,所以用十六进制数来表示二进制数是比较方便的。
十六进制数的基数是16,共有16个数码,它们是0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F。其中A表示十进制的10,余类推。
2. 十六进制数和二进制数之间的转换
由于十六进制数的基数是2的幂,所以这两种数制之间的转换是十分容易的。一个二进制数,只要把它从低位到高位每4位组成一组,直接用十六进制数来表示就可以了。
例1.5 0011 0101 1011 1111
3 5 B F
亦即0011010110111111B=35BFH
反之,把十六进制数中的每一位用4位二进制数表示,就形成相应的二进制数了。
例 1.6 A 1 9 C
1010 0001 1001 1100
亦即A19CH = 1010000110011100B
3. 十六进制数和十进制数之间的转换
各位十六进制数与其对应权值的乘积之和即为与此十六进制数相对应的十进制数。
例 1.7 N=BF3CH
=11×163+15×162+3×161+12×160
=11×4096+15×256+ 3×16+12×1
=48956D
十进制数转换为十六进制数也可使用降幂法和除法。
(1)降幂法
首先写出要转换的十进制数,其次写出小于该数的十六进制权值,然后找出该数中包含多少个最接近它的权值的倍数,这一倍数即相应位的值,用原数减去此倍数与相应位权值的乘积得到一个差值,再用此差值去找低一位的权值的倍数,如此反复直到差值为0为此。
例 1.8 N=48956D 小于N的十六进制权值为
4096 256 16 1
对应的十六进制数 B F 3 C
计算过程如下:
48956-11×4096 = 3900
3900 – 15 ×256 = 60
60-3×16 = 12
12-12×1 =0
所以N=48956D=(11)(15)(3)(12)=BF3CH
(2)除法
把要转换的十进制数的整数部分不断除以16,并记下余数,直到商为0为止。
例 1.9 N=489856D
48956/16=3059 (a0=12)
3059/16=191 (a1=3)
191/16=11 (a2=15)
11/16=0 (a3=11)
所以N=48956D=BF3CH。
对于要转换的十进制数的小数部分,则应不断地乘以16,并记下其整数部分,直到结果的小数部分为0为止。由于其方法与二、十进制数的转换方法是相同的,这里不再举例说明。显然,为把一个十进制数转换为二进制数,可以先把该数转换为十六进制数,然后再转换为二进制数,这样可以减少计算次数;反之,要把一个二进制数转换十进制数,也可采用同样的方法。
加法规则:0+0=0、0+1=1、1+0=1、1+1=0(进位1)
乘法规则:0×0=0、0×1=0、1×0=0、1×1=1
十六进制数的运算可以采用先把该十六进制数转换为十进制数,经过计算后再把结果转换为十六进制数的方法,但这样做比较繁琐。其实,只要按照逢十六进一的规则,直接用十六进制数来计算也是很方便的。
十六进制加法:当两个一位数之和S小于16时,与十进制数同样处理;如果两个一位数之和大于或等于16时,则应该用S-16及进位1来取代S。
例 1.10
05C3H
+ 3D25H
= 42E8H
十六进制数的减法也与十进制数类似,够减速时可直接相减,不够减时服从向高位借1为16的规则。
例 1.11
3D25H
- 05C3H
= 3762H
十六进制数的乘法可以用十进制数的乘法规则来计算,但结果必须用十六进制数表示。
例 1.12
05C3H
- 00ABH
=3F61
+ 399E
=3D941H
十六进制数的除法可以根据其乘法和减法规则处理。
计算机中的数是用二进制来表示的,数的符号也是用二进制表示的。在机器中,把一个数连同其符号在内数值化表示称为机器数。一般用最高有效位来表示数的符号,正数用0表示,负数用1表示。机器数可以用不同的码制来表示,常用的有原码、补码和反码表示法。由于多数机器的整数采用补码表示法,80x86机也是这样。
补码表示法中正数采用符号-绝对值表示,即数的最高有效位为0表示符号为正,数的其余部分则表示数的绝对值。例如,假设机器字长为8位,则[+1]补 =00000001,[+127]补 =01111111,[+0]补 =00000000。
当用补码表示法来表示负数时则要麻烦一些。负数用2n-|X|来表示,其中n为机器的字长。当n=8时,[-1]补=28-1=11111111,而[-127]补=28-127=10000001,显然,最高有效位为1表示该数符号为负。应该注意,[-0]补 =28 =00000000,所以在补码表示法中0只胡一种表示,即00000000。对于10000000这个数,在补码表示法中被定义为-128。这样,8位补码能表示数的范围为-128~127。
我们可以用一种比较简单的方法来写出一个负数的补码表示:先写出该负数相对应的正数补码表示(用符号-绝对值法),然后将其按位求反(即0变1,1变0),最后在末位(最低位)加1,就可以得到该负数的补码表示了。
例1.13 机器字长为16位,写出N=-117D的补码表示。
+117D可表示为 0000 0000 0111 0101
按位求反后为 1111 1111 1000 1010
末位加1后 1111 1111 1000 1011
用十六进制数表示为F F 8 B
即[-117D]补=FF8BH
例1.14 如机器字长为8位,则-46D的补码表示为:
+46D的补码表示为 0010 1110
按位求反 1101 0001
末位加1后 1101 0010
用十六进制数表示 D 2
即[-46]补=D2H
至此,我们已经学会了一个数的补码表示法。在这里,说明一下用补码表示数时的符号扩展问题。所谓符号扩展问题是指一个数从位数较少扩展到位数较多(如从8位扩展到16位,或从16位扩展到32位)时应该注意的问题。对于用补码表示的数,正数的符号扩展应该在前面补0,而负数的符号扩展则应该在前面补1。例如,我们已经知道如机器字长为8位时,则[+46]补=00101110,[-46]补=11010010;如果把它们从8位扩展到16位,则[+46]补=0000000000101110=002EH,[-46]补=1111111111010010=FFD2H。
下面,我们再来讨论一下n位补码表示的范围问题。8位二进制数可以表示28=256个数,当它们是补码表示的带符号数时,它们的表数范围是-128≤N≤+127。一般说来,n位补码表示的数的表数范围是:
-2n-1 ≤N≤ 2n-1-1
所以n=16时的表数范围是:-32768≤ N≤ +32767
在机器里,为了扩大表数范围,可以用两个机器字(高位字和低位字)来表示一个机器数,这种数称为双字长数或双精度数,其格式为:
其中高位字的最高有效位为符号位,高位字的低15位和整个低位字的16位联合组成31位数表示数值,因而低位字的最高有效位没胡符号意义,只有数值意义。双字长数的表数范围可扩大到:
-231 ≤N≤ 231-1
231≈2.15×109 ,可见表数范围扩大了许多。上图中每个字上的0,15是位编号,每个机器字都从低位开始给每一位以编号,所以从右至左依次编号为0,1,…,15。
80386及其后继机型的机器字长已扩展为32位。为了统一起见,80x86系统仍称32位字为双字,这样又有了8个字节64位的4字。
我们知道,对一个正数的补码表示按位求反后再在末位加1,可以得到与此正数相应的负数的补码表示。我们把这种对一个二进制数按位求反后在末位加1的运算称为求补运算。可以证明,补码表示的数具有以下特性:
[X]补→求补→[-X]补→求补→[X]补
这一特性在补码的加、减法运算中很有用。
补码的加法规则是:
[X+Y]补=[X]补+[Y]补
补码的减法规则是:
[X-Y]补=[X]补+[-Y]补
其中的[-Y]补只要对[Y]补求补就可得到。
在某些情况下,要处理的数全是正数,此时再保留符号位就没有意义了。我们可以把最高有效位也作为数值处理,这样的数称为无符号整数。8位无符号数的表数范围是0≤N≤255,16位无符号数的表数范围是0≤N≤65535,32位无符号数的表数范围是0≤N≤232-1。
在计算机中最常用的无符号整数是表示地址的数。此外,如双精度的低位字也是无符号整数等。在某些情况下,带符号的数(在机器中用补码表示)与无符号数的处理是有差别的,读者在处理时,应注意它们的区别。
计算机中处理的信息并不全是数,有时需要处理字符或字符串,例如从键盘输入的信息或打印输出的信息都是以字符方式输入输出的。因此,计算机必须能表示字符。字符包括:
字母:A、B、…、Z,a、b、…、z;
数字:0、1、…、9;
专用字符:+、-、*、/、SP(space空格)…;
非打印字符:BEL(Bell响铃)、LF(line feed换行)、CR(carriage return回车)、…;
这些字符在机器里必须用二进制数来表示。80x86机采用目前最常用的美国信息交换标准代码ASCII(American Standard Code for Information Interchange)来表示。这种代码用一个字节(8位二进制码)来表示一个字符,其中低7位为字符的ASCII值,最高位一般用作校验。
“与”运算又称逻辑乘,可用符号·或∧来表示。如有A、B两个逻辑变量(每个变量只能有0或1两种取值),可能有的取值情况只有4种,在各种取值的条件下得到的“与”运算结果只有当A、B两个变量的取值均为1时,它们的“与”运算结果才是1。
“或”运算又称逻辑加,可用符号+或∨来表示。“或”运算规则:即A、B两个变量中只要有一个变量取值为1,则它们“或”运算的结果就是1。
A |
“非”运算的规则,即非0为1,非1为0。
“异或”运算,即当两个变量的取值相异时,它们的“异或”运算结果为1。