fortran语言中的十六进制浮点

fortran语言中的十六进制浮点,fortran,floating-point-conversion,Fortran,Floating Point Conversion,Fortran中C中的“a”格式说明符是否有等价物 C例如: printf("%a\n",43.1e6); // 0x1.48d3bp+25 以十六进制格式导出浮点数可防止舍入错误。虽然舍入误差通常可以忽略不计,但能够准确恢复保存的值仍然是有利的。请注意,printf生成的十六进制表示是可移植的,并且是可读的 如何使用“a”说明符在Fortran中像在C中一样导出和解析浮点数 如果要获得完全精度,最好的方法是使用未格式化的文件,例如: program main real :: r in

Fortran中C中的“a”格式说明符是否有等价物

C例如:

printf("%a\n",43.1e6); // 0x1.48d3bp+25
以十六进制格式导出浮点数可防止舍入错误。虽然舍入误差通常可以忽略不计,但能够准确恢复保存的值仍然是有利的。请注意,printf生成的十六进制表示是可移植的,并且是可读的


如何使用“a”说明符在Fortran中像在C中一样导出和解析浮点数

如果要获得完全精度,最好的方法是使用未格式化的文件,例如:

program main
  real :: r
  integer :: i
  r = -4*atan(1.)
  open(20,access="stream")
  write (20) r
  close(20)
end program main
(我使用了Fortran 2003中新出现的流访问,因为 它通常比正常的无格式访问更容易混淆)。然后,您可以使用,例如,
od-t x1 fort.20
将其视为十六进制转储

您还可以使用
TRANSFER
将位模式复制为整数,然后使用Z编辑描述符


如果您真的想模仿%a说明符,您必须自己使用。大多数机器现在使用IEEE格式。使用
TRANSFER
将模式复制到一个整数,然后使用
i和
将其分开(用二的幂进行乘法或除法进行移位)。

另一种选择是让C库为您完成工作,并通过C绑定进行接口。这取决于现代编译器(使用了一些F2003特性)

模块x
内部用法::iso_c_绑定
私有的
公共:a_fmt
接口
子例程doit(a,dest,n)bind(C)
进口
实数(种类=c_双精度),值::a
字符(种类=字符),意图(输出)::dest(*)
整数,值::n
结束子例程doit
端接口
接口a_fmt
模块程序a_fmt_浮点,a_fmt_双精度
终端接口a_fmt
包含
函数a_fmt_浮点(a)结果(res)
真实(种类=浮点数),意图(单位):a
字符(len=:),可分配::res
res=a_fmt_double(实(a,种类=c_double))
结束函数a_fmt_float
函数a_fmt_双(a)结果(res)
真实(种类=c_双),意图(单位):a
字符(len=:),可分配::res
字符(len=30)::dest
整数::n
调用doit(a,dest,len(dest))
n=指数(目的地,亚喀尔(0))
res=dest(1:n)
结束函数a_fmt_double
端模x
主程序
使用x
隐式无
双精度::r
整数::i
r=-1./3.d0
i=11030吗
打印*,a_fmt(r)
r=-r*2.0
结束
主程序结束
#包括
void doit(双a,字符*dest,整数n)
{
snprintf(目的地,n-1,“%a”,a);
}

不能使用“Z”说明符导入使用“a”导出的数据。使用“Z”导出的浮点不能再标识为浮点,并且它们的表示是特定于计算机的。没有这样的描述符。您必须编写自己的输出转换。为了避免混淆,我删除了与“Z”说明符相关的所有内容。我只想知道Fortran中“a”的等价物。是的,直到现在我才意识到OP为什么需要这种格式,这真的不是一个好主意。1)“%a”的用处还在于其他应用程序的支持。例如,Mathematica可以用十六进制浮点数解析CSV文件。导入二进制数据要困难得多。2) 二进制数据的可移植性还取决于endianness和使用的特定精度。-我正在寻找与“a”格式说明符完全等效的格式,而不是任何其他存储浮点数的方法。@user3337813如果您关心可移植性,您可以始终使用netcdf、hdf等容器来存储阵列。您的选择是有限的。Fortran没有这样的描述符。您可以a)使用位洗牌(见上文)在Fortran中使用自己的翻滚b)使用Fortran特定的函数来拾取数字(甚至不那么困难)。c) 向Fortran标准委员会提出建议(不太可能成功)。d) 扩展像gfortran这样的开源编译器,并向gfortran团队提出补丁(困难得多)。
module x
  use, intrinsic :: iso_c_binding
  private
  public :: a_fmt
  interface
     subroutine doit(a, dest, n) bind(C) 
       import
       real(kind=c_double), value :: a
       character(kind=c_char), intent(out) :: dest(*)
       integer, value :: n
     end subroutine doit
  end interface

  interface a_fmt
     module procedure a_fmt_float, a_fmt_double
  end interface a_fmt

contains
  function a_fmt_float(a) result(res)
    real(kind=c_float), intent(in) :: a
    character(len=:), allocatable :: res
    res = a_fmt_double (real(a, kind=c_double))
  end function a_fmt_float

  function a_fmt_double(a) result(res)
    real(kind=c_double), intent(in) :: a
    character(len=:), allocatable :: res
    character(len=30) :: dest
    integer :: n
    call doit (a, dest, len(dest))
    n = index(dest, achar(0))
    res = dest(1:n)
  end function a_fmt_double

end module x

program main
  use x
  implicit none
  double precision :: r
  integer :: i
  r = -1./3.d0
  do i=1,1030
     print *,a_fmt(r)
     r = - r * 2.0
  end do
end program main

#include <stdio.h>

void doit (double a, char *dest, int n)
{
  snprintf(dest, n-1, "%a", a);
}