Debugging Fortran毕达哥拉斯三角恒等式有时不起作用
我正在使用Codeblocks+GNU Fortran 问题是我的计算如下:Debugging Fortran毕达哥拉斯三角恒等式有时不起作用,debugging,fortran,codeblocks,gfortran,Debugging,Fortran,Codeblocks,Gfortran,我正在使用Codeblocks+GNU Fortran 问题是我的计算如下: SQRT(1-COS*COS) 当我做这些计算很多次(几百万次)时,有时平方根下的值是负数,所以我得到的结果是NaN 我的研究表明,当计算负数的平方根时,COS等于“-1”。因此,fortran计算-1*-1是错误的,因为平方根下应该有0,但没有 有没有办法解决这个问题?这不仅关系到毕达哥拉斯三角恒等式,而且关系到平方根下的任何恒等式 SQRT(1-x*x) X在[-1,1]范围内 基本上,成本在我的程序中是这样定
SQRT(1-COS*COS)
当我做这些计算很多次(几百万次)时,有时平方根下的值是负数,所以我得到的结果是NaN
我的研究表明,当计算负数的平方根时,COS等于“-1”。因此,fortran计算-1*-1是错误的,因为平方根下应该有0,但没有
有没有办法解决这个问题?这不仅关系到毕达哥拉斯三角恒等式,而且关系到平方根下的任何恒等式
SQRT(1-x*x)
X在[-1,1]范围内
基本上,成本在我的程序中是这样定义的(我很抱歉在成本本身之前有点冗长的介绍,但事实就是这样):
XDET=0。
YDET=0。
ZDET=50。
半径=1。
x=半径*sqrt(ω)!ω=均匀分布的随机数[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
成本=AN2
如果(成本>1。)成本=1。
如果(成本<-1.)成本=-1。
SINT=SQRT(1.-成本*成本)
顺便说一句,AN2有时假设一个绝对零,在我捕获它之前也会导致NAN
另外,我还有一个EXP(X)的错误,X大于90表示为无穷大。我猜这是由于浮点数的精度有限。请看这里: 简单解决方案:
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 ) )
我猜这是由于浮点数的精度有限。请看这里: 简单解决方案:
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 ) )
PS识别为bug的原因很简单
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.999999999999999999
但表示该值的精度超过了可用的精度,该数字被四舍五入为1.0
虽然我仍然看不出
1.-COST*COST
会有什么负面影响,但您使用的浮点运算并不能让我确信您没有向我们展示的代码中没有细微的错误。对于您的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.999999999999999999
但表示该值的精度超过了可用的精度,该数字被四舍五入为1.0
虽然我仍然看不出
1.-COST*COST
会有什么负面影响,但你使用浮点运算并不能让我放心,在你没有向我们展示的代码中,没有细微的错误。除了余弦的域是[-1.0,1.0],当平方时,应该会得到[0.0,1.0]的域。函数不应该有否定的参数。Mark是对的。此外,对于整数值实变量,算术通常是精确的。除了余弦域为[-1.0,1.0],当其平方时,应导致域为[0.0,1.0]。函数不应该有否定的参数。Mark是对的。对于整数值实数变量,算法通常是精确的。您有多确定|COS
|永远不能大于1.0?请向我们展示您的代码。目前,表达式SQRT(1-COS*COS)
只有在COS
是变量名称时才能成功解析,它不是对内在函数COS
的调用,也不是对任何其他函数的调用。虽然AlexanderVogt可能是正确的,但我保留判断。High Performance Mark,请参阅编辑的文章中的代码摘录。您能否指定导致问题的gfortran版本和omega值?我测试了1000个随机数,但无法重现这个问题。朱晓蕾,很抱歉我提出了一个愚蠢的问题,但如果我的gfortran版本安装了代码块,我该如何确定它?你有多确定|COS
|永远不能大于1.0?请展示你的代码。目前,表达式SQRT(1-COS*COS)
只有在COS
是变量名称时才能成功解析,它不是对内在函数COS
的调用,也不是对任何其他函数的调用。虽然AlexanderVogt可能是正确的,但我保留判断。High Performance Mark,请参阅编辑的文章中的代码摘录。您能否指定导致问题的gfortran版本和omega值?我测试了1000个随机数,但无法重现这个问题。朱晓蕾,我很抱歉这个愚蠢的问题,但如果安装了代码块,我如何确定我的gfortran版本?是的,当我计算exp(90+)的实际值时,我得出了相同的结论。谢谢。嗯,我不是一个真正的f-p算法专家,特别是考虑到大部分代码都是由我的科学主管提供给我的,我可以做我的科学工作。如果你能指定我应该纠正什么以使程序更稳定,我很乐意这样做,因为我正在修复代码中的一些东西,因为我了解了更多关于Fortran的知识。如果你还没有,你应该熟悉维基百科关于浮点的文章。Alexande写的那篇论文