是否有等同于' a'在Fortran中从C中知道的格式说明符?
C示例:
printf("%a\n",43.1e6); // 0x1.48d3bp+25
以十六进制格式导出浮点数可防止舍入错误。虽然舍入误差通常可以忽略不计,但能够精确恢复保存的值仍然是有利的。请注意,printf生成的十六进制表示是可移植的,并且是人类可读的。
如何在Fortran中导出和解析浮点数,就像我在C中使用' a'一样。符?
答案 0 :(得分:1)
如果您想要完全精确,最好的方法是使用未格式化的文件,例如:
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
将模式复制到一个整数,然后使用IAND
(以及乘以2的乘法或除法进行移位)选择它。
答案 1 :(得分:1)
另一个选择是让C库为您完成工作并通过C绑定进行接口。这取决于现代编译器(使用了一些F2003功能)。
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);
}