【问题标题】:Getting double precision in fortran 90 using intel 11.1 compiler使用 intel 11.1 编译器在 fortran 90 中获得双精度
【发布时间】:2011-07-12 21:35:09
【问题描述】:
我有一个非常大的代码,它设置并迭代求解一个非线性偏微分方程系统,用 fortran 编写。我需要所有变量都是双精度的。在我为代码编写的附加模块中,我将所有变量声明为双精度类型,但我的模块仍然使用旧源代码中声明为实数类型的变量。所以我的问题是,当单精度变量乘以 fortran 中的双精度变量时会发生什么?如果用于存储值的变量声明为双精度,结果是否为双精度?如果一个双精度值乘以一个最后没有“D0”的常数呢?我可以在 Intel 11.1 中设置一个编译器选项来使所有实数/双精度/双精度常量吗?
【问题讨论】:
标签:
double
fortran
precision
【解决方案1】:
Fortran 标准对此非常具体;其他语言也是这样,这确实是您所期望的。如果一个表达式包含对两个不同精度的浮点变量的操作,则该表达式属于更高精度操作数的类型。例如,
(实变量)+(双变量)->(双)
(双变量)*(实变量)->(双)
(双变量)*(实常数)->(双)
等等
现在,如果您将结果存储在较低精度的浮点变量中,它将再次进行向下转换。但是,如果您将其存储在精度更高的变量中,它将保持其精度。
如果您担心单精度浮点变量会导致问题,您可以强制将其转换为双精度
使用 DBLE() 内在函数:
DBLE(实变量)-> 双精度
【解决方案2】:
Jonathan Dursi's answer 是正确的 - 您问题的另一部分是是否有办法使所有实变量都具有双精度。
您可以使用 ifort 编译器通过使用 -i8(对于整数)和 -r8(对于实数)选项来完成此操作。我不确定是否有办法强制编译器将文字解释为双精度而不指定它们(例如,通过将 3.14159265359 更改为 3.14159265359D0) - 我们不久前遇到了这个问题。
【解决方案3】:
所以我的问题是,在 fortran 中,单精度变量乘以双精度变量会发生什么? 单精度提升为双精度,运算以双精度完成。
如果用于存储值的变量声明为双精度,结果是双精度吗?不一定。右侧是一个不“知道”左侧变量精度的表达式,它将被存储在其中。如果你有 Double = SingleA * SingleB (使用名称表示类型),计算将以单精度执行,然后转换为双精度进行存储。这不会获得额外的计算精度!
如果一个双精度值乘以一个末尾没有“D0”的常数呢?这就像第一个问题一样,常数会提升为双精度,然后计算以双精度完成。 然而,这个常数仍然是单精度的,即使你写了很多数字作为双精度常数,内部存储是单精度的,不能代表那个精度。例如,DoubleVar * 3.14159265359 将以双精度计算,但将以双精度计算 DoubleVar * 3.14159。
如果你想让编译器在一个常量中保留很多数字,你必须指定一个常量的精度。 Fortran 90 执行此操作的方法是使用您需要的任何精度定义您自己的真实类型,例如,要求至少 14 个十进制数字:
integer, parameter :: DoubleReal_K = selected_real_kind (14)
real (DoubleReal_K) :: A
A = 5.0_DoubleReal_K
A = A * 3.14159265359_DoubleReal_K
【解决方案4】:
如果你写成 0.1D0 形式的数字,它将把它当作双精度数,否则如果你写 0.1,精度会在转换中丢失。
这是一个例子:
program main
implicit none
real(8) a,b,c
a=0.2D0
b=0.2
c=0.1*a
print *,a,b,c
end program
编译时使用
ifort main.f90
我得到结果:
0.200000000000000 0.200000002980232 2.000000029802322E-002
编译时使用
ifort -r8 main.f90
我得到结果:
0.200000000000000 0.200000000000000 2.000000000000000E-002
如果您使用 IBM XLF 编译器,则等价于
xlf -qautodbl=dbl4 main.f90