Fortran毕达哥拉斯三角形身份有时不起作用

时间:2013-12-05 13:06:21

标签: debugging fortran codeblocks gfortran

我正在使用Codeblocks + GNU Fortran。

问题是我的计算如下:

SQRT(1-COS*COS)

当我做这些计算很多(几百万次)时,有时平方根下的值是负的,因此我得到NaNs的结果。

我的努力表明,当计算负数的平方根时,COS等于“-1”。因此,fortran错误地计算-1 * -1,因为在平方根下应该有0但是没有。

有没有办法解决这个问题?这不仅涉及毕达哥拉斯三角恒等式,而且还涉及平方根看起来像

的任何东西
SQRT(1-x*x)

X在[-1,1]范围内。

基本上COST在我的程序中就是这样定义的(我为COST本身之前的一些冗长的介绍道歉,但事情就是如此):

XDET = 0.
YDET = 0.
ZDET = 50.
RADIUS = 1.

x = RADIUS*sqrt(omega)  !omega=random number in uniform distribution [0,1]
y = 0.
z = 1.E-20

DW=SQRT((XDET-X)**2+(YDET-Y)**2+(ZDET-Z)**2)
DWW = 1./DW
AN2=(ZDET-Z)*DWW

COST = AN2
if(COST > 1. ) COST = 1.
if(COST < -1.) COST = -1.
SINT = SQRT(1.-COST*COST)

顺便说一句,AN2有时会假设一个绝对零,导致NaNs也被困在它之前。

P.S。我也有一个EXP(X)的错误,X高于90,显示为INFINITY。

2 个答案:

答案 0 :(得分:1)

您的PS识别为错误的解释很简单

exp(90.0) > 3.4028235 x 10^38

3.4028235 x 10^38是单精度浮点数可以任意精度表示的最大正数。

当然,这种分析假设您的变量x是IEEE 32位浮点数。

另请注意,表达式ZDET-Z绝不会以单精度与1.0不同。 1.0 - 1.0e-20 == 0.9999999999999999999但是代表这个确切地超出了可用的精度,并且数字四舍五入为1.0

虽然我仍然看不出1.-COST*COST怎么会消极,但你使用浮点运算并不能让我放心,在你没有显示的代码部分中没有细微的错误我们。

答案 1 :(得分:0)

我的猜测是由于浮点数的精度有限。看看这里:What Every Computer Scientist Should Know About Floating-Point Arithmetic

简单的解决方案:

xx = x*x
if ( xx .gt. 1.e0 ) xx = 1.e0 ! 1.d0 for double precision

y = sqrt( 1.e0 - xx ) ! Again, 1.d0 for double precision

或者,作为一个单行:

 y = sqrt( 1.e0 - min( x*x, 1.e0 ) )