在Fortran中定义指数

时间:2017-11-16 19:01:49

标签: fortran precision intel-fortran

我的代码中的变量精度问题一直存在问题... 有一段时间我一直把变量声明为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个十进制大小写精度。

感谢您的帮助!

1 个答案:

答案 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