日常生活中,有各种各样的数,整数、分数、百分数等等,我们无时无刻不与这些数打
交道。如:用加班2 . 7 5小时获得的1倍半的钱来买半匣鸡蛋需支付8 . 2 5 %的销售税。许多人对
诸如此类的数都感到很适应,并不需要怎么在行,即使在听到“平均每个美国家庭有2 . 6人”
这样的统计数字的时候,也不会联想到2 . 6这个数字对人来说是不是要把人肢解了这样可怕的
问题。
在计算机内存里,整数和分数的换算是常见的。存在计算机内存里的东西都是二进制位
的形式,也就是说,都是二进制数。但有些数用位来表示比其他数用位来表示要容易一些。
我们使用位来表示数学上称为自然数而计算机编程人员称为正整型数的数,并介绍如何
用2的补码来表示负整数,而这种方法很容易实现正数、负数的加法。下表列出了8位、1 6位、
3 2位的正整数及它们的2的补码的范围:
数的位数正整数范围2的补码范围
8 0~2 5 5 -1 2 8~1 2 7
1 6 0~65 535 -32 768~32 767
3 2 0~4 294 967 295 -2 147 483 648~2 147 483 647
要介绍的就是这些。除了整数以外,数学上还定义了有理数,它们可表示成两个整数的
比,这个比也叫分数。例如, 3 / 4是一个有理数,因为它是3与4的比。可以把这个数写成小数
形式0 . 7 5,当写成小数时,它真正表示了分数,在此为7 5 / 1 0 0。
回忆一下第7章里的小数系统,在小数点左边的数字与1 0的整数次幂相关联;同样,在小
数点右边的数字与1 0的负整数次幂相关联。第7章用42 705.684作为例子,该数可以表示成与
下面与之相等的形式:
4×10 000+
2×1 0 0 0+
7×1 0 0+
0×1 0+
5×1+
6÷1 0+
8÷1 0 0+
4÷1 0 0 0
注意一下除号,可以把这个序列写成没有除号的形式:
4×10 000+
2×1 0 0 0+
7×1 0 0+
0×1 0+
5×1+
6×0 . 1+
8×0 . 0 1+
4×0 . 0 0 1
最后,可以用1 0的幂的形式表示如下:
4×1 04+
2×1 03+
7×1 02+
0×1 01+
5×1 00+
6×1 0-1+
8×1 0-2+
4×1 0-3
有些分数并不容易用小数表示,常见的如1 / 3。如果用3 去除1,可以得到:
0.3333333333333333333333......
而永无止境。我们通常写成简洁形式,在3 上面加一道横线来表示无限循环:
0 .-3
即使这样,把1 / 3写成小数也是有些笨拙的。它还是一个分数,因为它是两个整数的比。同样,
1 / 7是:
0.142857142857142857...... 或0.142857
无理数则更不同,如2的平方根。无理数不能表示成两个整数的比,也就是说,小数部分
是无穷的,没有重复规律或固定模式:
2的平方根是下面这个代数方程的根:
x2 - 2 = 0
如果一个数不是以整数为系数的代数方程的根,则称为超越数(所有的超越数为无理数,
但并不是所有的无理数都是超越数)。超越数包括p,它是圆的周长与直径的比,近似值为:
3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 8 4 6 2 6 4 3 3 8 3 2 7 9 5 0 2 8 8 4 1 9 7 1 6 9 3 9 9 3 7 5 1 1 . . . . . .
另一个超越数是е,它是下面表达式:
当n趋近于无穷大时的近似值:
2.71828182845904523536028747135266249775724709369996...
到现在为止,谈到的所有数—有理数和无理数—统称为实数。这种定义用来与虚数相
区分。虚数是负数的平方根,复数是由虚数和实数组成的。不管名称如何,虚数揭示了现实
世界的奥秘,可以用来(例如)解决电子学的一些高级问题。
习惯上,我们把数看成是连续的。如果给出两个有理数,则可以找出一个数在这两个数
中间。实际上,只需取平均值即可。但是,数字计算机不能处理连续事件。位不是0就是1,
244 编码的奥秘
下载
1+
1
n
æ
è
ç
ö
ø
÷
n
第23章定点数和浮点数245
下载
没有中间值。由于这一特性,数字计算机必须处理离散值。可以表示的离散值的个数直接与
可达到的二进制位数相关。例如:如果用3 2位来存放正整数,则可以存放0~4 294 967 295个
整数。如果需要存放4 . 5这个数,则必须重新考虑一种方法并做一些改动。
小数可以表示成二进制吗?是的,可以。最容易的方法可能是二进制编码的十进制
(B C D)。前面第1 9章讲到B C D是十进制数的二进制编码,每一个十进制数字( 0、1、2、3、
4、5、6、7、8和9)需要4位,如下表所示:
十进制数字二进制数字
0 0 0 0 0
1 0 0 0 1
2 0 0 1 0
3 0 0 11
4 0 1 0 0
5 0 1 0 1
6 0 11 0
7 0 111
8 1 0 0 0
9 1 0 0 1
B C D码特别适用于用美元和美分表示的与钱数有关的计算机程序。银行和保险公司是两
个典型的多与钱打交道的行业,对这类公司的计算机程序来说,许多分数只需要两个十进制
数位。
通常1个字节存储两个B C D数字,有时将这称为压缩B C D码。2的补码不与B C D一起使用,
因此,压缩B C D码通常要有额外的一位(称作符号位)来标明是正数还是负数。一个B C D数存
入整个字节比较方便,所以,小小的符号位通常需要牺牲4位或8位的存储空间。
来看一个例子。假定计算机要处理的钱数不会超过正、负1 0 0 0万,换句话说,需要表示
的钱数的范围从-9 999 999.99~9 999 999.99,则存储在内存的每一笔钱数需要用5个字节来
表示。例如,-4 325 120.35用5个字节表示为:
00010100 00110010 01010001 00100000 00100101
或用十六进制表示为:
14h 32h 51h 20h 25h
注意最左边的1用来表示负数,即符号位。如果是正数,则该位为0。每一个数字需要4位,
从十六进制值中可以直接看到。
如果需要表示的数的范围从- 99 999 999.99~99 999 999.99,则需要6个字节—1 0个数
字占5个字节,另一个字节仅用来表示符号位。
这类存储和标记方法也称作定点格式,因为小数点通常固定在特定的位置—本例中,小
数点在两个小数位之前。注意,实际上并没有什么东西与数一起存放用来标明小数点的位置。
处理定点格式数的程序应该知道小数点在哪里。定点数可以有任意个小数位数,在同一计算
机程序里可以混用这些数字,但是对这些数进行算术运算的那部分程序必须知道小数点的位
置。
定点格式只在知道这些数不会超过预先确定的内存单元,且没有太多小数位的场合比较适
用。在数可能很大或可能很小的场合定点格式完全不适用。假设保留一个内存区域用来存储以
英尺为单位的距离,则存在的问题是距离可能超出范围。从地球到太阳的距离是490 000 0 0 0 0 0 0
246 编码的奥秘
下载
英尺,氢原子的半径为0 . 0 0 0 0 0 0 0 0 0 2 6英尺,则你需要1 2字节的定点存储空间来容纳这些可能
很大也可能很小的数值。
如果你还记得科学家和工程师们喜欢用称为“科学记数法”的系统来表示数的话,你也
许已找到更好的存储此类数的方法。科学记数法特别适用于表示很大和很小的数,因为它采
用1 0的幂方法从而不用写很长的一串0。采用科学记数法后,数字
490 000 000 000 写成4 . 9×1 011
数字
0.00000000026 写成2 . 6×1 0-1 0
在这两个例子里,数字4 . 9和2 . 6称作小数部分或首数,有时也称作有效数(尽管这个词更
适用于对数运算)。为了与计算机术语相协调,在这儿把科学记数法的这一部分称作有效数。
指数部分是1 0的幂。在第一个例子中,指数是11;在第二个例子中,指数是- 1 0。指数
用来指明有效数的小数点要移动的位数。
为方便起见,有效数通常大于或等于1而小于1 0。尽管下面的数字是相等的:
4 . 9×1 011=4 9×1 01 0=4 9 0×1 09=0 . 4 9×1 01 2=0 . 0 4 9×1 01 3
但我们选用第一种格式。这种格式也称作科学记数法的规格化格式。
注意,指数符号只是标明数的大小而并不表示数本身是正的还是负的。下面是用科学记
数法表示的两个负数的例子:
-5 . 8 1 2 5×1 07 等于-58 125 000
和
-5 . 8 1 2 5×1 0-7 等于-0 . 0 0 0 0 0 0 5 8 1 2 5
在计算机中,对应于定点表示法的是浮点表示法。浮点格式用来存储较小或较大的数比
较理想,因为它是以科学记数法为基础的。但是,计算机中采用的浮点格式是用科学记数法
表示的二进制数。这里首先要提到的是如何用二进制表示小数数字。
实际上,这比设想的要容易,在十进制表示中,小数点右边的数字具有1 0的负整数次
幂;在二进制表示中,二进制小数点(也仅是一个点,看起来与十进制小数点一样)右边的
数具有2 的负整数次幂。例如,一个二制数:
1 0 1 . 11 0 1
可以用以下表达式转换成十进制:
1×4+
0×2+
1×1+
1÷2+
1÷4+
0÷8+
1÷1 6
除号可以用2 的负整数次幂替换:
1×22+
0×21+
1×20+
1×2-1+
1×2-2+
0×2-3+
1×2-4
或者,2的负整数次幂可以从1开始重复除以2来计算:
1×4+
0×2+
1×1+
1×0 . 5+
1×0 . 2 5+
0×0 . 1 2 5+
1×0 . 0 6 2 5
通过这些计算得到1 0 1 . 11 0 1等效的十进制数5 . 8 1 2 5。
在十进制科学记数法中,规格化有效数通常大于或等于1而小于1 0。同样,二进制科学记
数法的规格化有效数也通常大于或等于1而小于1 0(即十进制中的2)。所以,按二进制科学记
数法,数
1 0 1 . 1101 表示成1 . 0 111 0 1×22
这个规则隐含了一件有趣的事实:通常二进制浮点数在二进制小数点的左边除了1以外再
没有别的了。
现代计算机和计算机程序按照I E E E在1 9 8 5年制定的标准来处理浮点数,这个标准也为
ANSI(the American national standards institute ,美国国家标准局)所认可。A N S I / I E E E
S t d 7 5 4-1 9 8 5称作I E E E二进制浮点数算术运算标准。它并不像一般标准那样长,只有1 8页,
但却奠定了以方便的方式编码二进制浮点数的基础。
I E E E浮点数标准定义了两个基本格式:单精度格式,需要4个字节;双精度格式,需要8
个字节。
首先看一下单精度格式,它有三部分: 1位个符号位(0表示正, 1表示负)、8位的指数位
和2 3位的有效数位。如下所示,最低有效数在最右边:
总共有3 2位,4个字节。因为规格化二进制浮点数的有效数通常在二进制小数点左边为1,
所以在I E E E格式中这一位不包含在浮点数的存储空间中。有效数的2 3位小数部分是反被存储
的部分,所以,即使只有2 3位用来存储有效数,精度仍然认为是2 4位的。过一会儿将要看到
2 4位精度的意义。
8位指数范围从0~2 5 5,称为移码指数,意思是必须从指数中减去一个数(称为偏移量)
才能确定有符号指数的实际值。对单精度浮点数,偏移量为127 。
第23章定点数和浮点数247
下载
s=1位符号e=8位指数f=23位有效数
指数0和2 5 5用于特殊用途,在此简单描述一下。如果指数从1变化到2 5 4,则由s(符号位)、
e(指数)和f(有效数)来表示的数为:
(-1)s×1 . f×2e-1 2 7
-1的s次幂是数学上的一种方法,意思是“如果s为0,则数是正的(因为任何数的0次幂
等于1);如果s为1,则数是负的(因为- 1的1次幂为-1)”。
表达式的另一部分是1 . f,意思是1后面为二进制小数点,再后面为2 3位的有效小数部分。
它乘以2的幂,其中指数为内存中的8位移码指数减去1 2 7。
注意,到现在还没有提到如何表示一个很常见的数字,那就是0。这是一种特殊情况,
即:
• 如果e等于0,且f等于0,则数为0。通常,所有3 2位均为0则表示0。但是符号位可以是1,
在这种情况下,数被解释为- 0。-0可以表示一个很小的数,小到在单精度格式中不能
用数字和指数来表示。尽管如此,它们然小于0。
• 如果e等于0,且f不等于0,则数是有效的。但是,它不是规格化的数,它等于
(-1)s×0 . f×2- 1 2 7
注意,二进制小数点左边的有效数为0。
• 如果e等于2 5 5,且f等于0,则数为正或负无穷大,这取决于符号s。
• 如果e等于2 5 5,且f不等于0,该值被认为“不是一个数”,简写为N a N。N a N可以表示一
个不知道的数或者一个无效操作的结果。
通常,单精度浮点格式中可以表示的最小规格化的正或负二进制数为:
1 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0T W O×2-1 2 6
在二进制小数点之后有2 3个0。在单精度浮点格式中可以表示的最大规格化的正或负二进
制数为:
1 . 11111111111111111111111T W O×21 2 7
换算或十进制,这两个数近似为1 . 1 7 5 4 9 4 3 5 1×1 0-3 8和3 . 4 0 2 8 2 3 4 6 6×1 03 8。这就是单精度
浮点数表示法的有效范围。
前面讲过,1 0位二进制数近似等于3位十进制数。也就是说,若1 0位都置1 (即十六进制为
3 F F h,十进制为1 0 2 3 ),则它近似等于3位十进制都设置为9,即9 9 9。或者
21 0≈1 03
这种关系表明按单精度浮点格式存放的2 4位二进制数大约与7位十进制数等效。因此,也
可以说单精度浮点格式提供2 4位二进制精度,或大约7位十进制精度。它的含义是什么呢?
当观察定点数的时候,数的精度是很显然的。例如,对于钱数,用两位十进制小数的定
点数就可精确到分。但是,对浮点数来说,就不能这么肯定了。根据指数值的不同,有时浮
点数可以精确到比分还小的单位,有时甚至不能精确到元。
粗略地讲,单精度浮点数可精确到1 / 22 4,或1 / 1 6 7 7 7 2 1 6,或约百万分之六。这到底是什么
意思呢?
从某种意义上讲,它意味着如果想用单精度浮点数来表示16 777 216和16 777 217,其结
果是一样的。而且,在这两个数之间的任何数(如16 777 216.5)也认为是与它们一样的。所
248 编码的奥秘
下载
第23章定点数和浮点数249
下载
有这3个十进制数都按3 2位单精度浮点数
4 B 8 0 0 0 0 0 h
来存放。当把此数分成符号位,指数和有效数位时,如下所示:
0 10010111 00000000000000000000000
也即为
1 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0T W O×22 4
下一个表示的最大有效数是16 777 218,它的二进制浮点表示为:
1 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1T W O×22 4
两个不同的十进制数却以相同的浮点数存放可能是也可能不是一个问题。
如果是为银行编写程序且用单精度浮点数来存储元、分等,则你可能会很苦恼地发现
$262 144.00与$262 144.01是一样的。两个数字都是:
1 . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0T W O×21 8
这就是当处理元、分的时候,为什么要用定点数的原因。在处理浮点数的时候,可能还会发
现其他足以使人发疯的小毛病。程序原本计算的结果是3 . 5 0却成了3 . 4 9 9 9 9 9 9 9 9 9 9 9。浮点计算
中这种事情经常发生,但也没有别的更好的处理方法。
如果想用浮点表示法,又不想出现单精度那样的问题,可以用双精度浮点格式。这样的
数需要8个字节来存放,格式如下:
指数偏移量为1 0 2 3,即3 F F h,所以,以这种格式存放的数为
(-1)s×1 . f×2e-1 0 2 3
它具有与单精度格式中所提到适用于0、无穷大和N a N等情形相同的规则。
最小的双精度浮点格式的正数或负数为
(1 . 0 . . . . . . 0)T W O×2-1 0 2 2
5 2个0
最大的数为
(1 . 1 . . . . . . 1)T W O×21 0 2 3
5 2个1
用十进制表示,它的范围近似为2 . 2 2 5 0 7 3 8 5 8 5 0 7 2 0 1 4×1 0-3 0 8~1 . 7 9 7 6 9 3 1 3 4 8 6 2 3 1 5 8×
1 03 0 8。1 0的3 0 8次幂是一个非常大的数,在1 后面有3 0 8个十进制零。
5 3位有效数(包括没有包含在内的那1位)的精度与1 6个十进制位表示的精度十分接近。
相对于单精度浮点数来说这种表示要好多了,但它仍然意味着最终还是有一些数与另一些数
是相等的。例如,140 737 488 355 328.00与140 737 488 355 328.01是相同的,这两个数按照
6 4位双精度浮点格式存储,结果都是:
4 2 E 0 0 0 0 0 0 0 0 0 0 0 0 0 h
可把它转换为:
s=1位符号e=11位指数f=52位有效数
250 编码的奥秘
下载
(1 . 0 . . . . . . 0)T W O×24 7
5 2个0
当然,开发一种格式用来在存储器中存储浮点数只是在汇编语言程序中实际使用这些数
的工作中的一小部分。如果真的要研制与世隔绝的计算机,则你需要面对编写浮点数的加、
减、乘、除的函数集的工作。幸运的是,这些工作可以被分解成许多小的只涉及到整数的加、
减、乘、除的工作,而整数的四则运算我们已经知道如何实现了。
例如,浮点加法的关键是有效数相加,因而用的技巧是用两个数的指数部分确定有效数
如何移位。假设要做以下加法:
(1 . 11 0 1×25)+(1 . 0 0 1 0×22)
需要把111 0 1与1 0 0 1 0相加,但不是就这样相加。指数部分的不同表明第二个数必须进行
移位。实际上,需要进行111 0 1 0 0 0和1 0 0 1 0的整数加法。最后的和是:
1 . 1111 0 1 0×25
有时两个数的指数部分差距很大,其中一个数甚至对和没有影响。就像这种情况:把地
球到太阳的距离与氢原子的半径相加。
两个浮点数的相乘是把有效数部分像整型数那样相乘并把两个整型指数相加。通常,规
格化有效数部分可能会引起对新的指数调整一、二次。
浮点算术运算中另一个复杂问题牵涉到较麻烦的计算,如方根、幂、对数和三角函数。
但是,所有这些工作都可以用四个基本的浮点操作:加、减、乘、除来完成。
例如,三角函数S i n可以通过下列展开式来计算,如下:
参数x必须是弧度, 3 6 0度的弧度为2 p。感叹号是阶乘符号,其含义是把1到该数之间的所
有整数相乘,如: 5 !=1×2×3×4×5。这只是进行乘法运算,其中每一项的指数部分也是乘
法。其余的是一些除法、加法和减法。唯一真正麻烦的部分是在最后的省略,它意味着要永
远地计算下去。然而,实际上,如果局限在0~p / 2的范围(从这里可以推导出所有其他的正
弦函数值),并不需要进行多少展开运算。在展开大约1 2项以后,已经精确到了双精度数的5 3
位。
当然,使用计算机是为了使人们更容易完成某些工作,所以,编写浮点运算程序这样的
工作似乎离使用计算机的目的相差甚远。然而,这正是软件的可爱之处:一旦某人为某台机
器编写了浮点运算程序,其他人都可以使用。对科学和工程应用程序来说,浮点运算非常重
要,所以通常有很高的优先权。在计算机出现的早期,一旦新的类型的计算机出来,编写浮
点运算程序通常是第1项软件工作。
事实上,甚至可以设计计算机机器码指令直接进行浮点运算!显然,说起来容易做起来
难,但这也说明了浮点运算的重要性。如果可以用硬件来实现浮点运算—与1 6位微处理器
的乘法和除法指令一样—则计算机中所有浮点运算工作将会完成得更快。
最早把浮点运算硬件作为选件的商用计算机是1 9 5 4年的IBM 704,7 0 4把所有的数按3 6位
来存储。对浮点数,分成2 7位的有效数、8位指数和1个符号位。浮点运算硬件可做加法、减
法、乘法和除法,其他浮点运算功能必须用软件来实现。
桌面机的浮点运算硬件出现在1 9 8 0年,当时I n t e l发布了8 0 8 7数字数据协处理器芯片,一
种集成电路芯片,今天通常称为数学协处理器或浮点运算单元(floating-point unit,F P U)。
8 0 8 7之所以称为协处理器是因为它不能自己单独使用,它只能与8 0 8 6或8 0 8 8一起使用, 8 0 8 6
和8 0 8 8是I n t e l的第一个1 6位微处理器。
8 0 8 7有4 0个引脚,使用许多与8 0 8 6和8 0 8 8相同的信号。微处理器和数学协处理器通过这
些信号连接起来。当C P U收到一个特殊指令—称为E S C,代表E s c a p e—则协处理器接管系
统控制权并执行下一条机器代码,即包括三角运算、指数、对数运算的6 8条指令中的一条。
数据类型以I E E E标准为基础。那时, 8 0 8 7被认为是所生产的最高级的集成电路。
可以认为协处理器是一个小的自包含的计算机。在响应某个浮点运算机器码指令时(例
如,计算平方根的F S Q RT指令),协处理器内部执行存放在R O M中的自己的指令序列,这些
内部指令称为微代码。这些指令通常是循环的,所以计算结果并不是马上可用。尽管如此,
一般来说,数学协处理器至少比用软件来实现的同样例程要快1 0倍。
初始的IBM PC主板在8 0 8 8芯片的右边有一个4 0管脚的插槽供8 0 8 7用。遗憾的是,这个插
槽是空的,需要加速浮点运算的用户必须单独购买8 0 8 7并自己把它安装上。即使在安装了数
学协处理器后,并不是所有的应用程序都可以运行得更快,一些应用程序—如,文字处理
程序—几乎不需要浮点运算。其他如电子报表程序则要用到很多浮点计算。这些程序能够
运行得更快,但并不是所有程序都是如此。
可以看到,程序员必须用协处理器机器码指令来编写特定的代码供协处理器执行。因为
数学协处理器不是硬件的标准部分,因而许多程序员怕麻烦不愿意做。但是,他们还是不得
不编写自己的浮点运算子程序(因为许多人并没有安装数学协处理器),所以支持8 0 8 7芯片就
成为一个额外的负担—一个不小的负担。最终,如果他们程序运行的机器上有数学协处理
器,程序员要学会编写利用数学协处理器的应用程序;如果没有,则要编写浮点运算仿真程
序。
经过几年后, I n t e l还发布了用于2 8 6芯片的2 8 7数学协处理器,用于3 8 6的3 8 7数学协处理
器。但对于1 9 8 9年发布的Intel 486DX,F P U已经做在了C P U里面,而不再是作为一个选件!
遗憾的是,1 9 9 1年I n t e l发布了一种低价格的4 8 6 S X,它没有把F P U做在C P U里面,而是提供了
4 8 7 S X数学协处理器作为一个选件。1 9 9 3年发布的P e n t i u m芯片却再一次使做在C P U内部的
F P U成为标准,也许以后永远会这样。M o t o r o l a在它的6 8 0 4 0微处理器里集成了F P U,该微处
理器于1 9 9 0年发布。以前,M o t o r o l a销售6 8 8 8 1和6 8 8 8 2数学协处理器用来支持早先6 8 0 0 0家族
的微处理器。P o w e r P C芯片也把浮点运算硬件集成在内部。
尽管浮点运算硬件对专门从事汇编语言程序设计的程序员来说是一个很好的礼物,但是,
与2 0世纪5 0年代早期开始的其他一些工作相比这只是微不足道的进步。
作者在 2010-10-13 10:26:47 发布以下内容