在 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
?我特别要求双精度 real
s,但如果有 kind
独立的方法来做到这一点,我会优先考虑那个答案。大概可以使用 "EXCESSIVE PRECISION" 方法,但也可以为简洁性加分。
你要的格式是ES24.17
通常情况下,如果您的十进制数字多于数据类型可以表示的三位,则不会丢失任何位。所以对于双精度 IEEE 浮点数,这将是 18 位数字。
您的第二种格式使用了 ifort 支持但 gfortran 不支持的非标准语法。我不推荐使用它。
Fortran 2018 提供 "hex format" 实数值,保留所有位,但我认为只有 C/C++ 理解它。
假设我希望以可移植的方式将双精度值写入 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
?我特别要求双精度 real
s,但如果有 kind
独立的方法来做到这一点,我会优先考虑那个答案。大概可以使用 "EXCESSIVE PRECISION" 方法,但也可以为简洁性加分。
你要的格式是ES24.17
通常情况下,如果您的十进制数字多于数据类型可以表示的三位,则不会丢失任何位。所以对于双精度 IEEE 浮点数,这将是 18 位数字。
您的第二种格式使用了 ifort 支持但 gfortran 不支持的非标准语法。我不推荐使用它。
Fortran 2018 提供 "hex format" 实数值,保留所有位,但我认为只有 C/C++ 理解它。