【发布时间】:2017-02-09 16:44:40
【问题描述】:
我在从地理坐标转换为地心坐标的子例程中遇到浮点异常问题。变量geo(x) 作为纬度和经度对输入子程序。变量xyz(x) 输出为三组分量(x -- 格林威治子午线和赤道;y -- 90 度经度和赤道;z -- 北极)。
subroutine geo2xyz(geo,xyz)
IMPLICIT REAL*8 (A-H,O-Z)
dimension geo(2),xyz(3)
rr=6367443.5
xyz(1)=rr*sind(90.-geo(1))*cosd(geo(2))
xyz(2)=rr*sind(90.-geo(1))*sind(geo(2))
xyz(3)=rr*cosd(90.-geo(1))
return
end
我意识到sind 和cosd 是非标准函数,但它们通过适当的转换链接到目标文件。我之前已经对此进行了测试,它适用于使用度数而不是弧度的其他代码:
real function sind(x)
IMPLICIT REAL*8 (A-H,O-Z)
sind=sin(x*3.141592653589793d0/180.0d0)
return
end
real function cosd(x)
IMPLICIT REAL*8 (A-H,O-Z)
cosd=cos(x*3.141592653589793d0/180.0d0)
return
end
我尝试使用 GDB 浏览该程序,但无法找出问题所在。似乎方程中的所有变量都可以,但是xyz(1) = 1,如果我用计算器进行计算,情况并非如此。
Program received signal SIGFPE, Arithmetic exception.
0x0000000100001cb8 in geo2xyz (geo=..., xyz=...) at disslip.f:758
758 xyz(1)=rr*sind(90.-geo(1))*cosd(geo(2))
(gdb) print xyz(1)
$1 = 1
(gdb) print rr
$2 = 6367443.5
(gdb) print geo(1)
$3 = 50.350000000000001
(gdb) print geo(2)
$4 = -127.55800000000001
(gdb)
我在这里遗漏了什么导致浮点异常?我敢肯定这很简单,我对此很陌生。
【问题讨论】:
-
如何调用子程序?参数的值是什么?使用
implicit none和模块。它将使您免于许多问题。几十年来,对于体面的风格来说,隐含的无几乎是必需的。 -
你确定调试器给出了正确的位置吗?我会检查一些打印语句,这很奇怪。我们必须知道实际调用的是哪个函数。在suvroutine或更好使用的模块中添加
external sind和external cosd。 -
@VladimirF 不幸的是,这是自 80 年代中期以来由许多人编写的大量代码的一部分,因此已过时。我需要付出巨大的努力来更新风格。该子例程在其他地方调用如下:
call geo2xyz(rgeo,rxyz)rr、geo(1) 和 geo(2) 的值是正确的,但不应导致 xyz(1)=1,因此我假设调试器已正确识别问题线。 -
那么
external呢?我建议这些事情来找出正在发生的事情,不仅仅是为了风格,它们是调试的一部分。顺便说一句,如果您删除所有returns,程序将保持不变,只是更短且更易于阅读。
标签: floating-point fortran gdb sigfpe