gfortran 4.8.5处理的SIGFPE错误
我使用的是一个计算流体动力学软件,它是在Ubuntu 16.04 LTS上用gfortran 4.8.5版编译的。该软件可以编译为单精度或双精度和-O3优化选项。由于我没有必要的计算资源以双精度运行CFD软件,因此我使用单精度和以下选项进行编译gfortran 4.8.5处理的SIGFPE错误,fortran,gfortran,fortran90,floating-point-exceptions,Fortran,Gfortran,Fortran90,Floating Point Exceptions,我使用的是一个计算流体动力学软件,它是在Ubuntu 16.04 LTS上用gfortran 4.8.5版编译的。该软件可以编译为单精度或双精度和-O3优化选项。由于我没有必要的计算资源以双精度运行CFD软件,因此我使用单精度和以下选项进行编译 ffpe-trap=invalid,zero,overflow 我在一行包含asin函数的代码中得到一个SIGFPE错误- INTEGER, PARAMETER :: sp = SELECTED_REAL_KIND( 6, 37) !< sin
ffpe-trap=invalid,zero,overflow
我在一行包含asin函数的代码中得到一个SIGFPE错误-
INTEGER, PARAMETER :: sp = SELECTED_REAL_KIND( 6, 37) !< single precision
INTEGER, PARAMETER :: wp = sp
REAL(KIND=wp) zsm(:,:)
ela(i,j) = ASIN(zsm(ip,jp))
我们在Fortran中有和函数,因此我认为我们可以使用与中相同的方法,即,asin(max(-1.0,min(1.0,x))
。我用gfortran-4.8和7.1尝试了以下测试:
program main
implicit none
integer, parameter :: sp = selected_real_kind( 6, 37 )
integer, parameter :: wp = sp
! integer, parameter :: wp = kind( 0.0 )
! integer, parameter :: wp = kind( 0.0d0 )
real(wp) :: x, a
print *, "Input x"
read(*,*) x
print *, "x =", x
print *, "equal to 1 ? :", x == 1.0_wp
print *, asin( x )
print *, asin( max( -1.0_wp, min( 1.0_wp, x ) ) )
end
在我的电脑上,wp=sp
(或wp=kind(0.0)
)
如果需要修改大量asin(x)中的
asin(x)
,并且程序依赖于C或Fortran预处理器,则可以方便地定义一些类似宏的
#define clamp(x) max(-1.0_wp,min(1.0_wp,x))
如果我们想删除这样的修改,我们可以简单地将clamp()的定义更改为
#define clamp(x)(x)
。另一种方法可能是定义一些asin2(x)
函数,将x
限制为[-1,1],并用asin2
替换内置的asin
(作为宏或Fortran函数)。看起来不错。我明天会试试。你能用我的精度-整数、参数::sp=SELECTED\u REAL\u KIND(6,37)INTEGER、参数::wp=sp修改你的答案吗?好的,我修改了代码以便使用“wp=sp”(实际上,种类(0.0)等取决于平台和编译器选项…)。我希望测试代码也适用于gfortran以外的编译器(尚未测试!)
program main
implicit none
integer, parameter :: sp = selected_real_kind( 6, 37 )
integer, parameter :: wp = sp
! integer, parameter :: wp = kind( 0.0 )
! integer, parameter :: wp = kind( 0.0d0 )
real(wp) :: x, a
print *, "Input x"
read(*,*) x
print *, "x =", x
print *, "equal to 1 ? :", x == 1.0_wp
print *, asin( x )
print *, asin( max( -1.0_wp, min( 1.0_wp, x ) ) )
end
$ ./a.out
Input x
1.00000001
x = 1.00000000
equal to 1 ? : T
1.57079625 (<- 1.5707964 for gfortran-4.8)
1.57079625
$ ./a.out
Input x
1.0000001
x = 1.00000012
equal to 1 ? : F
NaN
1.57079625
$ ./a.out
Input x
1.0000000000000001
x = 1.0000000000000000
equal to 1 ? : T
1.5707963267948966
1.5707963267948966
$ ./a.out
Input x
1.000000000000001
x = 1.0000000000000011
equal to 1 ? : F
NaN
1.5707963267948966
#define clamp(x) max(-1.0_wp,min(1.0_wp,x))