fortran语言中的十六进制浮点
Fortran中C中的“a”格式说明符是否有等价物 C例如: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
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);
}