《数值分析(原书第2版)》—— 0.3 实数的浮点表示

简介:

本节书摘来自华章出版社《数值分析(原书第2版)》一 书中的第0章,第0.3节,作者:(美)Timothy Sauer,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

0.3 实数的浮点表示

在本节中,我们将描述浮点数的计算机算术模型.相关的模型有好几个,但是为了简化我们选择一个特定的模型并进行详尽描述.我们选择的模型被称为IEEE 754浮点标准.电子与电气工程师学会(IEEE)在工业标准的制定方面表现出积极的兴趣,其浮点算术格式成为计算机工业中单精度和双精度浮点算术的通行标准.
当使用有限精度的计算机内存来表示真实、无穷精度数字的时候,舍入误差不可避免.尽管我们希望在长的计算中生成的较小的误差对于结果仅有较小的影响,但是事实表明在很多情况下这仅仅是一厢情愿.简单算法,诸如高斯消去或者微分方程的求解方法,能够把极微小的误差放大到极大的规模.实际上,本书的一个主要议题就是要使读者意识到由于计算机造成的小误差使得计算面临不可靠的危险,并且要知道如何避免或最小化这样的危险.

0.3.1 浮点格式

IEEE标准包含一组实数的二进制表示.一个浮点数字包含三个部分:符号(+或者-)、尾数(包含一串有效数位)和一个指数,这些部分都在一个计算机字里.
有三种浮点数常用的精度级别:单精度、双精度和扩展精度(也称为长双精度).对于三种浮点数精度级别分配的数位分别是32、64和80.这些数位被分成如下不同的部分:
screenshot

三种精度以相同的方式运行.标准化的IEEE浮点数表示为±1.bbb…b×2p(0.6)其中N个b中的每个b是0或者1,p是一个M位的二进制数表示指数.如式(0.6)所示的标准化意味着,主导数位(最左边的一位)必须是1.
当一个二进制数用一个标准浮点数字表示的时候,它被称为“左对齐”,8意味着其中最左边的一个数位1被平移到小数点的左边,平移通过指数的变化进行补偿.例如,一个十进制数9,对应的二进制数1001保存为+1.001×23平移3位,或者与23相乘,就可以将最左边的1平移到正确的位置.
为了一致描述三种精度的浮点数字,下面我们将专门对双精度格式进行大量讨论.单精度和长双精度将以相同的方式进行处理,与双精度的主要差异仅仅在指数和尾数的长度M和N.大量C编译器和MATLAB所使用的双精度数字中,M=11,N=52.
1的双精度表示为
+1.0000000000000000000000000000000000000000000000000000×20其中有52位的尾数.下一个比1大的浮点数是
+1.0000000000000000000000000000000000000000000000000001×20或者1+2-52.
定义0.1 机器精度对应的数字,记做εmach,是1和比1大的最小浮点数之间的距离.对于IEEE双精度浮点表示,εmach=2-52十进制数9.4=(1001.0110)2表示为如下的左对齐数字:+1.0010110011001100110011001100110011001100110011001100110…×23其中的前52位表示为尾数.新的问题又出现了:我们如何以有穷数位拟合用于表示9.4的无穷数位?
我们必须以某种方式对数字进行截断,并且在这个过程中仅仅引入较小的误差.我们的方法被称为截断,通过简单丢弃在末端之外的数位来实现,也就是说,那些超过小数点右边第52位的数字直接被丢掉.这种策略十分简单,但是由于这种方法通常会把结果向0的方向移动,所以它是一个有偏的方式.
另一种方法是舍入.对于十进制,如果下一位的数字是5或者比5大,数字通常向上进位,否则舍去.在二进制中,如果数位为1,则向上进位.具体来说,在双精度浮点数字中,小数点右边的第53位是一个重要数位,它也是第一个在给定数位空间之外的数位.IEEE标准中执行的默认的舍入技术里,当第53位是1时,给第52位加1(向上进位),当第53位是0时,第52位没有变化(舍去).仅有一个例外,如果第52后面的数位是10000…,正好在向上进位和舍去的中间,我们依据如何使得第52位等于0来确定向上进位或者舍去的选择.(这里我们仅仅处理尾数,符号位并不起作用.)
为什么这里会有这种奇怪的例外情况?除去这种情况,规则意味着舍入得到的标准浮点数字和原始数字最接近——这也是它名字的由来,即最近舍入法则.舍入造成的误差有同等可能生成向上或者向下的误差.而这种例外情况中,有两个距离原始数字相等的舍入浮点数字,采用的舍入方法不能表现出系统地向上或者向下的倾向.我们试图避免由于有偏的舍入造成在长计算中不想要的缓慢漂移.当出现这种平局问题,简单使得最后一位(第52位)的值为0的方法看起来十分随意,但是至少这样的选择没有表现出来对于向上或者向下的舍入倾向.习题0.3中的问题8解释了为什么在遇到平局时可以随意9选择0.
IEEE舍入最近法则
对于浮点精度,如果在二进制数右边的第53位是0,则向下舍去(在第52位后面截断).如果第53位是1,则向上进位(在第52位上加1),除了在1右边的所有已知位都是0,在这种情况下当且仅当第52位是1时在第52位上加1.
对于前面讨论的数字9.4,二进制数字右边的第53位是1,后面还有其他非0的数位.根据舍入最近法则进行向上进位,或者在第52位上加1.因而,表示9.4的浮点数字是+1.0010110011001100110011001100110011001100110011001101×23(0.7)定义0.2 将IEEE双精度浮点数字记做x,利用舍入最近法则记做fl(x).
在计算机算术中,实数x用一串数位fl(x)替换.根据这个定义,fl(9.4)是数字的二进制表示(0.7).我们通过去掉最右边无穷长的数字尾巴0.1100×2-52×23=0.0110×2-51×23=0.4×2-48得到浮点表达.并在舍入过程中加上2-52×23=2-49.因而fl(9.4)=9.4+2-49-0.4×2-48
=9.4+(1-0.8)2-49
=9.4+0.2×2-49(0.8)换句话说,利用双精度浮点数和舍入最近法则的计算机,当保存9.4时可能生成0.2×2-49的误差.我们把0.2×2-49称作舍入误差.
在这里重点是用于表示9.4的浮点数和9.4并不相等,尽管它们非常接近.为了度量它们之间的差异,我们使用误差的标准定义.
定义0.3 令xc是计算版本x的精确度量,则绝对误差=xc-x
相对误差=xc-xx (若x的度量存在,即x≠0)(0.9)

对于数字x=9.4,我们算出式(0.8)对应的舍入误差,该误差满足式(0.9):fl(9.4)-9.49.4=0.2×2-499.4=847×2-52<12εmach10例0.2 找出浮点数表示fl(x)以及对应的舍入误差,x=0.4.
由于(0.4)10=(0.0110)2,将二进制数左对齐得到0.4=1.100110×2-2
=+1.1001100110011001100110011001100110011001100110011001
 100110…×2-2因而,依据舍入法则,fl(0.4)是+1.1001100110011001100110011001100110011001100110011010×2-2这里,在第52位上加了1,由于二进制加法的进位使得第51位也发生了改变.
通过认真分析,我们在截断过程中舍弃2-53×2-2+0.0110×2-54×2-2,并在舍入过程中加上2-52×2-2.因而,fl(0.4)=0.4-2-55-0.4×2-56+2-54
=0.4+2-54(-1/2-0.1+1)
=0.4+2-54(0.4)
=0.4+0.1×2-52注意到,舍入过程中对于0.4的相对误差是0.1/0.4×εmach=1/4×εmach,服从式(0.9).

0.3.2 机器表示

到目前为止,我们已经描述了摘要中的浮点数表示.现在我们将讲述更多关于如何在计算机中实现这种表示的细节.同样,在本节中我们将讨论双精度浮点格式;其他格式具有相似的实现.
每个双精度浮点数字被分配了8字节,或者64位,来存储其对应的三个部分.每个字都具有如下的形式se1e2…e11b1b2…b52(0.10)其中第1位保存了符号位,后面11位用于保存指数,再后面小数点后的52位保存尾数.符号位是0表示正数,1表示负数.11位的指数表示的正二进制整数,这些正数通过往指数上叠加210-1=1023得到,指数范围在-1022和1023之间.e1…e11覆盖了从1到2046之间对应的指数,由于特殊目的,这里没有使用0和2047,我们在后面会讨论这些没有使用的指数.
数字1023称为双精度格式的指数偏差.它用于把正和负指数转化为正的二进制数保存在指数位中.对于单精度和长双精度,指数偏差位分别是127和16383.
MATLAB的format hex使用16个连续的十六进制,或者16个基对应的数字表示式(0.10)中的64位机器数字.因而,最前面的3个十六进制数字表示了指数和符号部分,后面的13位则包含尾数.
例如,数字1,或者1=+1.0000000000000000000000000000000000000000000000000000×2011具有如下的双精度机器数字形式0011111111110000000000000000000000000000000000000000000000000000一旦将1023加到指数部分.前三个十六进制数字对应001111111111=3FF因而浮点数字1的十六进制表达将变成3FF0000000000000.可以在MATLAB中键入format hex,并键入数字1进行检查.
例0.3 寻找实数9.4的十六进制机器数字表达.
从式(0.7)可知,符号位s=0,指数为3,小数点后面的52位是0010110011001100110011001100110011001100110011001101     →(2CCCCCCCCCCCD)16
向指数上添加1023得到1026=210+2,即(10000000010)2.符号和指数部分结合在一起是(010000000010)2=(402)16,得到对应的十六进制形式4022CCCCCCCCCCCD.
现在我们回过头来看特殊的指数值0和2047.后者2047,如果尾数位串都是0用于表示∞,否则表示NaN,意味着“不是一个数字”.由于2047用11个1来表示,或者e1e2…e11=(111 1111 1111)2,Inf和-Inf的前12位分别是011111111111和111111111111余下的52位(尾数)都是0.机器数NaN也是由111111111111开始,但是具有非0的尾数.总的来说,
机器数例子十六进制数+Inf1/07FF0000000000000-Inf-1/0FFF0000000000000NaN0/0FFFxxxxxxxxxxxxx
其中x表示不全为0的位.
特殊的指数0,意味着e1e2…e11=(000 0000 0000)2,也表示对于标准浮点数字形式的背离.在这种情况下,机器数字解释为非标准的浮点数字±0.b1b2…b52×2-1022(0.11)换句话说,在这种情况下,最左边的数位不再被假设为1.这些非标准化数字称作异常(subnormal)浮点数字.通过更多的量级扩展了数字的表示范围.因而,2-52×2-1022=2-1074是最小的可表达双精度数字.它对应的机器字是
0000000000000000000000000000000000000000000000000000000000000001我们需要确切理解最小可表达数字2-1074和εmach=2-52之间的差异.许多在εmach=2-52以下的数字都是机器可表达的数字,尽管将这些数字加到1上可能没有什么影响.而另一方面,在2-1074以下的双精度数字完全不能12被表示.
异常数字包括最重要的数字0.实际上,异常表达包括两个不同的浮点数字,+0和-0,在计算中它们被看做两个相同的实数.+0的机器表达具有符号位s=0,指数位e1…e11=00000000000,52个尾数都是0;简单来说,所有64位都是0.+0的十六进制表达是0000000000000000.对于数字-0,所有位都完全相同,除了符号位s=1.对于-0的十六进制表达是8000000000000000.

0.3.3 浮点数加法

机器加法首先对齐进行加法的两个数字的小数点位,接着相加,然后再次把结果保存为浮点数字.相加由于在特定用途的加法寄存器中进行,因而本身可以更高的精度进行(以多于52位进行).在相加之后,必须通过舍入变回52位以存储二进制的机器数字.
例如,在2-53上加1看起来如同如下表示:1.00…0×20+1.00…0×2-53
=1.0000000000000000000000000000000000000000000000000000×20
+0.00000000000000000000000000000000000000000000000000001×20

=1.00000000000000000000000000000000000000000000000000001×20根据舍入法则,这将被保存为1.×20=1,因而,1+2-53和双精度IEEE算术中的1相等.我们注意到,2-53是具有这种性质的最大的一个浮点数字;在计算机算术上,任何一个更大的数字加到1上会带来一个比1大的和.
在IEEE模型中,εmach=2-52并不意味着比εmach小的数字可以忽略.只要它们在模型中是可表达的,假设这些数字不是和单位大小的数字进行相加或者相减,对这些数字进行计算也是精确的.
由于截断和舍入的存在,计算机算术有时可以给出令人惊讶的结果.例如,如果一个具有双精度的计算机利用IEEE舍入最近法则保存9.4,然后减去9,然后再减去0.4,结果竟然不是0!在这个过程中发生了如下情形:首先,9.4如前所示被保存为9.4+0.2×2-49.当减去9的时候(注意到在计算机中9的表示没有任何误差),结果是0.4+0.2×2-49.现在要求计算机减去0.4(见例0.2)对应的机器数fl(0.4)=0.4+0.1×2-52,这会留下0.2×2-49-0.1×2-52=0.1×2-52(24-1)=3×2-53而不是0.这个数字很小,和εmach量级相同,但是它们不是0.由于MATLAB的基本数据类型是IEEE精度数字,我们将在MATLAB中展示这个过程:
screenshot
screenshot

例0.4 计算双精度浮点的求和(1+3×2-53)-1.
显而易见,在实数算术中结果为3×2-53.但是,浮点算术的结果可能并不相同.注意到3×2-53=2-52+2-53.第一次相加为1.00…0×20+1.10…0×2-52
=1.0000000000000000000000000000000000000000000000000000×20
+0.00000000000000000000000000000000000000000000000000011×20

=1.00000000000000000000000000000000000000000000000000011×20这又是一个对于舍入原则的例外情况.由于求和之后的第52位是1,我们必须向上进位,这意味着给第52位加1.计算之后,我们得到+1.0000000000000000000000000000000000000000000000000010×20这对应于1+2-51的表达.因而,减1之后,结果变为2-51,这与2εmach=4×2-53的值相等.又一次,我们注意到计算机算术和精确算术之间的差别.使用MATLAB可以检查这个结果.
在MATLAB中计算,或者在任意一个使用IEEE标准的浮点计算的编译器中的计算,都遵从在本节中描述的精度法则.尽管浮点计算和精确算术不同,可以得到令人惊讶的结果.这通常是可预测的.最近舍入原则是一个典型的默认舍入原则,尽管如果愿意,可以通过使用不同编译器设置而采用其他的舍入原则.比较不同舍入策略对应的结果,有时可作为一个非正式方式判断计算的稳定性.
单单一个小的舍入误差,或者相对εmach大小的误差,可以把有意义的计算拉离正轨,这看起来十分令人惊讶.在下节中我们引入一个处理该问题的机制.更一般地,误差放大和误差条件的研究在第1章、第2章和后面的章节中常常出现.

0.3节习题

1.将下面基为10的数字转化为二进制,并使用舍入最近法则表示为一个浮点数字fl(x):
(a) 1/4 (b) 1/3 (c) 2/3 (d) 0.914
2.将下面基为10的数字转化为二进制,并使用舍入最近法则表示为一个浮点数字fl(x):
(a) 9.5 (b) 9.6 (c) 100.2  (d) 44/7
3.找出一个正整数k,使得数字5+2-k可以用双精度浮点算术精确表示(没有舍入误差)?
4.找出最大的整数k,使得在双精度浮点算术中fl(19+2-k)>fl(19).
5.使用IEEE双精度浮点算术利用最近舍入法则手工计算下面的求和公式.(使用MATLAB检查计算结果.)
(a) (1+(2-51+2-53))-1(b) (1+(2-51+2-52+2-53))-1
6.使用IEEE双精度浮点算术利用最近舍入原则手工计算下面的求和计算:
(a) (1+(2-51+2-52+2-54))-1(b) (1+(2-51+2-52+2-60))-1
7.把下面给定的数字用MATLAB格式的十六进制写出来.然后在MATLAB中检查结果.
(a) 8 (b) 21 (c) 1/8 (d) fl(1/3) (e) fl(2/3) (f) fl(0.1) (g) fl(-0.1) (h) fl(-0.2)
8.在双精度浮点算术中利用IEEE最近舍入法则,1/3+2/3是否精确等于1?将需要使用习题1中的fl(1/3)和fl(2/3).这个结果是否有助于解释为什么这个法则如此表达?如果不使用IEEE舍入,而仅仅截断52位后面的位数是否会得到相同的结果?
9.(a) 解释为什么使用IEEE双精度和IEEE最近舍入法则的计算机上通过计算(7/3-4/3)-1可以确定机器精度.(b) (4/3-1/3)-1是否也可以确定εmach?通过转化为浮点数字并进行机器算术来解释.
10.在双精度浮点算术中确定是否1+x>1,使用最近舍入法则.
(a) x=2-53(b)x=2-53+2-60
11.对于IEEE计算机,加法结合律是否成立?
12.寻找IEEE双精度浮点表示fl(x),寻找与给定真实数字之间的差异fl(x)-x.检查相对误差不大于εmach/2.
(a) x=1/3(b) x=3.3(c) x=9/7
13.有64个双精度浮点数字,其对应的64位机器表示只有一个非零位.试图寻找所有数字中(a) 最大者,(b) 第二大者,(c) 最小者.
14.使用IEEE双精度计算机算术,手工进行下面的操作,使用最近舍入原则.(使用MATLAB检查结果.)
(a) (4.3-3.3)-1(b) (4.4-3.4)-1(c) (4.9-3.9)-1
15.使用IEEE双精度计算机算术,手工进行如下操作.使用最近舍入原则.
(a) (8.3-7.3)-1(b) (8.4-7.4)-1(c) (8.8-7.8)-115
16.寻找IEEE双精度表示fl(x),寻找与给定真实数字之间的差异fl(x)-x.检查相对误差不大于εmach/2.
(a) x=2.75(b) x=2.7(c) x=10/3

相关文章
|
索引 Windows
【计算机系统】整数与浮点数【详解】(一)
【计算机系统】整数与浮点数【详解】(一)
571 0
【计算机系统】整数与浮点数【详解】(一)
|
3月前
|
存储 编译器 C语言
魔性的float浮点数精度问题
魔性的float浮点数精度问题
25 0
|
9月前
【软考学习3】数据表示——浮点数计算 + 单精度浮点数IEEE754计算
【软考学习3】数据表示——浮点数计算 + 单精度浮点数IEEE754计算
191 0
|
11月前
|
存储
二进制浮点数的加减法运算
二进制浮点数的加减法运算
|
11月前
|
编译器 C++
C++ 字符串转浮点数,包括整数、小数和科学记数法
C++ 字符串转浮点数,包括整数、小数和科学记数法
296 0
定点数与浮点数简单解释
定点数 定点数:小数的位置是固定不变的。定点数又包括定点整数和定点小数。 定点小数:小数点隐含固定在最高数据位的左边,整数位则用于表示符号位,用于表示纯小数。
176 0
定点数与浮点数简单解释