The Perils of FloatingPoint
Copyright (c) 1996 Lahey Computer Systems, Inc. Permission to copy isgranted with acknowledgement of the source.
原文参见 The Perils of Floating Point
[译]浮点数的危害
By wttttt
@2016.10.24【庆祝这个伟大的程序员的节日?233】
如果没有数字电脑的浮点数能力,许多伟大的程序员和科学家们可能不会有近些年的进展。然而,即使对有着多年数学经验的人而言,一些浮点数的计算结果还是看起来十分奇怪。我将试图解释这其中一些奇怪结果的产生原因,并在适当时给出一些建议。
浮点数表示和计算是不精确的,但是我不认为这对程序员而言是十分麻烦的。许多输入值是测量结果,它们本身就是不精确的,因此关于输出值的问题不在于是否存在错误,而在于错误被预料的程度。然而,当你可以在脑海里计算的结果比比电脑用它的浮点数计算结果更精确时,你就会开始感到怀疑了。
我使用FORTRAN编写我的例子,原因如下:
1. FORTRAN比其他的计算机语言有更多的浮点数计算;
2. 我在Lahey Computer Systems公司工作,它们开发和销售FORTRAN语言系统。
二进制浮点数
许多奇怪结果的核心根本都是:计算机的浮点数通常是二进制的,然而外部表示是十进制的。我们预计1/3将不会是可精确表示的,但是直觉上似乎.01是可以的。不是这样的!.01在IEEE单精度表示是10737418/1073741824或近似地0.009999999776482582。你甚至可能没有注意到这些区别,知道你看到如下所示的代码:
REAL X
DATA X/.01/
IF ( X* 100.d0 .NE. 1.0 ) THEN
PRINT *, 'Many systems print this surprisingresult. '
ELSE
PRINT *, 'And some may print this.'
ENDIF
十进制浮点数实现没有这种奇怪现象。然而,十进制浮点数实现是很稀少的,因为在数字电脑中二进制计算要快很多。
不精确性
数字电脑上的浮点数运算的不精确性是天性的。一个32位浮点数的24比特(包括隐藏比特)尾数近似地表示7个重要的十进制数字。不想连续的实数系统,一个浮点数系统在数字之间时有间隔的。如果一个数字是不可精确表示的,那么它一定是通过最近的可表示的值来近似的。
因为相同数量的数字被用来表示所有的正常化的数字,所以样品数量越小,可表示数字的密度越大。比如,在1.0和2.0之间近似有8,388,607个单精度数字,然而1023.0和1024.0之间仅仅有大约8191个单精度数字。
在任意计算上,数学上等价的表达式使用浮点计算可以产生不同值。在如下例子中,Z和Z1将有不同值,因为(1/Y)或者1/7在二进制浮点数中是不可精确表示的。
REALX, Y, Y1, Z, Z1
DATAX/77777/, Y/7/
Y1 = 1/ Y
Z = X/ Y
Z1 = X* Y1
IF (Z.NE. Z1) PRINT *, 'Not equal!'
END
不重要的数字
如下的示例代码阐述了一个现象--看起来重要的无意义的数字:
REALA, Y
DATA Y/1000.2/ ! About 7 digits ofprecision in Y
A = Y- 1000.0 ! About 3 significantdigits in result
PRINT*, A ! Prints 0.200012
END
一个单精度(实数)实体可以最大表示大约7个十进制精度数字,因此