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

What is a portable format to fully express a double-precision value in 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

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

   3.14159265358979
       3.1415926535897931
   3.141592653589793
        3.14159265358979311600
另一方面,

gfortran(gcc 版本 4.8.2)要求第二个输出语句的宽度,因此编译失败。注释掉第二个输出语句 '(f)' 允许编译,结果(这里添加了一个空行)是:

   3.1415926535897931

   3.141592653589793
        3.14159265358979311600

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

您会发现结果各不相同。我希望 none 的结果是准确的,但对机器精度来说是准确的。当然,对于大多数用途,~15 位数字是可以接受的,但我对全精度输出很好奇,因此数字可以通过 ASCII 输出在程序之间传递而不会丢失精度。

我的问题

是否有一种可移植的方法可以完全精确地输出 real?我特别要求双精度 reals,但如果有 kind 独立的方法来做到这一点,我会优先考虑那个答案。大概可以使用 "EXCESSIVE PRECISION" 方法,但也可以为简洁性加分。

你要的格式是ES24.17

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

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

Fortran 2018 提供 "hex format" 实数值,保留所有位,但我认为只有 C/C++ 理解它。