13.4 避免极值
有些表达式在输入参数是某些特殊值时会出现极端现象,如结果是无穷大,这会导致计算错误。这种现象很多,也没有什么好的通用的解决方法,一般通过检测和表达式变形避免计算错误。本节用一个例子说明这个问题。
在下面的分析中,假设溢出异常已被屏蔽,且按第2章的论述设置了适当的返回值。代码中所有数据类型均是双精度格式(即double类型)。
13.4.1 问题的提出
考虑通过直角坐标计算夹角的表达式:
- theta = arcos(x/sqrt(x*x + y*y))
这个表达式的数学含义如图13-1所示。
这个表达式当x→±∞时,theta→0.0或 。但是,在计算过程中,当x→±∞时,x*x+y*y、x*x、x会依次出现溢出,导致结果可能出错。
当x→±∞时,有下列两种情形:
(1)x*x+y*y或x*x溢出,x没有溢出
由于x*x+y*y或x*x溢出,x*x+y*y的计算结果是+∞,故sqrt(x*x+y*y)得到+∞。由于x没有溢出,是个有限值,x/sqrt( x*x + y*y )=>x/+∞得到0.0。最后,得到的theta=arcos(0.0)是 /2,是错误的。
算例:x=1.0E+300、y=1.0,theta=1.5707963267948966(真值是1.0E-300)。
(2)x溢出
由于x溢出,因此x*x和x*x+y*y必然溢出,得到±∞/+∞。这是一个非法运算,因此得到NaN。于是,theta=arcos(NaN),得到NaN,是错误的。
算例:x=1.0E+310、y=1.0,theta=NaN(真值是1.0E-310)。
【责任编辑:
董书 TEL:(010)68476606】