在 Fortran 中完全表达双精度值的可移植格式是什么?

jvr*_*sem 6 precision formatting portability ascii fortran

假设我希望以可移植的方式将一个双精度值写入 ASCII 文件,使其达到全精度。(显然,原始二进制输出是表达数字的最紧凑的方式,但这不是我在这里要问的。)

我想要另一个程序,例如用 MATLAB 或 Python 编写,能够读取文件并存储与 Fortran 程序内部相同的确切值。

默认的 ASCII 输出简单地完成如下:

program main
   use, intrinsic :: ISO_FORTRAN_ENV, only : dp=>REAL64, stdout=>OUTPUT_UNIT
   implicit none

   real(kind=dp), parameter :: pi = 3.141592653589793238462643383279502884197_dp

   write(stdout,*) pi            ! Test the default format 
   write(stdout,'(f)') pi        ! Test the specific decimal default format
   write(stdout,'(f20.15)') pi   ! Probably sufficient precision...
   write(stdout,'(f30.20)') pi   ! EXCESSIVE PRECISION!

end program main
Run Code Online (Sandbox Code Playgroud)

我知道不同的编译器可能有不同的格式默认值和要求。例如,ifort编译上面的例子没有问题,并产生以下输出:

   3.14159265358979
       3.1415926535897931
   3.141592653589793
        3.14159265358979311600
Run Code Online (Sandbox Code Playgroud)

gfortran(gcc version 4.8.2) 另一方面,第二个输出语句需要一个宽度,所以编译失败。注释掉第二个输出语句'(f)'允许编译,结果(此处添加空行)为:

   3.1415926535897931

   3.141592653589793
        3.14159265358979311600
Run Code Online (Sandbox Code Playgroud)

我无法访问nagfor也没有安装任何其他 Fortran 编译器,所以我不在这里测试它们。

您会注意到结果各不相同。我希望没有一个结果是精确的,而是精确到机器精度。当然,对于大多数用途,大约 15 位数字是可以接受的,但我对全精度输出很好奇,因此可以通过 ASCII 输出在程序之间传递一个数字而不会损失精度。

我的问题

有没有一种便携式方法可以输出real全精度?我特别要求双精度real,但如果有一种kind独立的方式来做到这一点,我会优先考虑那个答案。据推测,人们可以使用“EXCESSIVE PRECISION”方法,但也可以使用简洁的加分项。

Ste*_*nel 5

通常情况下,如果您的十进制数字比数据类型可以表示的多三个,则不会丢失任何位。所以对于双精度 IEEE 浮点数,这将是 18 位数字。

您的第二种格式使用 ifort 支持但 gfortran 不支持的非标准语法。我不推荐使用它。

Fortran 2018 为实数值提供“十六进制格式”,保留所有位,但我认为只有 C/C++ 理解它。

  • 是的。示例值为:-15.625 EX14.4E3 -0X1.F400P+003 (2认同)