在Fortran中,我对恒定数字的精确性有困难。
我是否需要将每一个0.1写成0.1d0才能实现双精度?我知道编译器有一个标记,例如gfortran中的-fdefault-real-8,它解决了这种问题。这会是一种便携可靠的方法吗?如何检查标志选项是否真正适用于我的代码?
我使用F2py在我的Python代码中调用Fortran代码,即使我给出了一个未指定的标志,它也不会报告错误,这就是我担心的。
发布于 2018-06-19 02:04:45
你的问题的答案是:是的,你确实需要指出常数是双精度的。使用0.1是这个问题的一个常见例子,因为4字节和8字节表示是不同的.其他常量(如0.5),其中扩展的精度字节都为零,没有这个问题。
这是在F90的Fortran中引入的,并给许多遗留的FORTRAN代码的转换和重用带来了问题。在F90之前,双精度a= 0.1的结果可以使用实际的0.1或双0.1常数,尽管我使用的所有编译器都提供了一个双精度值。在用已发布的结果测试遗留代码时,这可能是不一致结果的常见来源。例子经常被报道,例如PI=3.141592654在本周的一个论坛上的代码中。
但是,使用0.1作为子例程参数总是会引起问题,因为这将作为一个真正的常量来传递。
因此,考虑到实际常量是如何处理的历史,您确实需要在需要时显式指定双精度常量。这不是一种用户友好的方法。
发布于 2018-06-18 19:44:12
在Fortran程序中,1.0始终是一个默认的实文本常量,而1.0d0总是一个双精度的文字常量。
然而,“双重精度”在不同的语境中意味着不同的事物。
在Fortran上下文中,“双重精度”指的是一种特定类型的实值,它比默认的实类具有更高的精度。在更一般的通信中,“双精度”通常被理解为一种特定的符合IEEE浮点规范的64位的真实类型。
gfortran的编译器标志-fdefault-real-8意味着默认的实数需要8个字节,并且很可能是编译器用来表示IEEE双精度的值。
因此,1.0是一个默认的实文本常量,而不是一个双精度的文字常量,但是缺省的实值可能恰好与IEEE的双精度相同。
像this one这样的问题在文字常量中反映了精度的含义。如果有人问我关于像-fdefault-real-8这样的旗帜的建议,我会说要避免它们。
发布于 2018-06-18 22:29:42
此外,我认为,由于双重精度定义可能在不同平台和编译器之间发生变化,因此使用标准Fortran约定显式声明所需类型的常量是一种很好的做法,如下所示:
program test
use, intrinsic :: iso_fortran_env, only: RK => real64
implicit none
write(*,"(*(g20.15))") "real64: ", 2._RK / 3._RK
write(*,"(*(g20.15))") "double precision: ", 2.d0 / 3.d0
write(*,"(*(g20.15))") "single precision: ", 2.e0 / 3.e0
end program test使用gfortran编译此代码将提供:
$gfortran -std=gnu *.f95 -o main
$main
real64: .666666666666667
double precision: .666666666666667
single precision: .666666686534882 在这里,前两行(64位实类和双精度类的显式请求)的结果是相同的。但是,通常情况下,情况可能不是这样,双精度结果可能取决于编译器标志或硬件,而real64类型将始终符合64位真实类型计算,而不管默认的真实类型。
现在考虑另一种情况,一个人已经声明一个真正的变量是64位的,然而,数值计算是以32位的精度进行的,
program test
use, intrinsic :: iso_fortran_env, only: RK => real64
implicit none
real(RK) :: real_64
real_64 = 2.e0 / 3.e0
write(*,"(*(g30.15))") "32-bit accuracy is returned: ", real_64
real_64 = 2._RK / 3._RK
write(*,"(*(g30.15))") "64-bit accuracy is returned: ", real_64
end program test它提供了以下输出,
$gfortran -std=gnu *.f95 -o main
$main
32-bit accuracy is returned: 0.666666686534882
64-bit accuracy is returned: 0.666666666666667 尽管变量被声明为real64,但第一行的结果仍然是错误的,因为它们不符合双精度类型(您希望的64位)。原因是,计算首先以文字常量的请求(默认为32位)精度完成,然后存储在64位变量real_64中,因此,从输出中的第二行的更准确的答案中得到一个不同的结果。
因此,底线信息是:使用“下划线”约定,显式声明Fortran中的文字常量的类型是一个好做法。。
https://stackoverflow.com/questions/50915600
复制相似问题