在fortran的十六进制浮点

时间:2015-01-28 10:43:12

标签: fortran floating-point-conversion

是否有等同于' a'在Fortran中从C中知道的格式说明符?

C示例:

printf("%a\n",43.1e6); // 0x1.48d3bp+25

以十六进制格式导出浮点数可防止舍入错误。虽然舍入误差通常可以忽略不计,但能够精确恢复保存的值仍然是有利的。请注意,printf生成的十六进制表示是可移植的,并且是人类可读的。

如何在Fortran中导出和解析浮点数,就像我在C中使用' a'一样。符?

2 个答案:

答案 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);
}