我的代码中的变量精度问题一直存在问题...
有一段时间我一直把变量声明为real(kind=8) :: var
,我现在明白这不是很便携,并且有一些其他的复杂情况,但基本上我在数值计算中得到了很多不精确。
现在我正在使用:
INTEGER, PARAMETER :: R8 = SELECTED_REAL_KIND (30, 300)
with variable declaration: real(R8) :: var1,var2.
在我通常将变量初始化为var1 = 1.0D0
之前,现在我正在使用var1 = 1.0_R8
,但我应该如何处理var1 = 1.0D-20
?我运行了一个简单的代码,证明1.0D-20
不会给我一个准确的结果,但像10.0_r8**(-20.0_r8)
这样的东西会。有更简单的方法来定义变量吗?我知道1D-20
非常小,但我使用的代码确实需要30个十进制大小写精度。
感谢您的帮助!
答案 0 :(得分:1)
这里真的发生了两件事。首先,使用d
表示法声明指数与将其声明为double precision
类型相同。
其次,您声明的r8
变量需要比大多数(全部?)8字节表示更精确。所以你实际上将大多数变量声明为quad,然后将它们初始化为double,这是你问题的根源。
如评论中所述,您明确问题的答案是使用以下符号声明指数
real(mytype) :: a = 1.23e-20_mytype
这种表示法很麻烦,但很容易习惯于不断声明。
这是我用来测试你的类型的一些示例代码:
program main
use ISO_FORTRAN_ENV, only : REAL64 => REAL64, REAL128
implicit none
INTEGER, PARAMETER :: R8 = SELECTED_REAL_KIND (30, 300)
real(r8) :: x, y, z
real(REAL64) :: a, b, c
x = 1.23d-20
y = 1.23e-20_r8
z = 1.23_r8*(10._r8**-20)
write(*,*) x
write(*,*) y
write(*,*) z
a = 1.23d-20
b = 1.23e-20_REAL64
c = 1.23_REAL64*(10._REAL64**-20)
write(*,*) a
write(*,*) b
write(*,*) c
write(*,*) 'Types: ', REAL64, R8, REAL128
end program main
对于Intel 16.0,这给出了:
mach5% ifort main.f90 && ./a.out
1.230000000000000057423043720037598E-0020
1.230000000000000000000000000000000E-0020
1.230000000000000000000000000000002E-0020
1.230000000000000E-020
1.230000000000000E-020
1.230000000000000E-020
Types: 8 16 16