9

我有一些浮点数需要从 Fortran 程序中输出。假设最大数字可能是 999.9999,它们都是非负数。我需要在所有小于 100 的数字前填充零。

例如,如果我有 25.6893782、245.354567 和 1.2345678,我需要以类似的形式将它们打印出来

025.6894
245.3546
001.2346

我怎样才能做到这一点?T例如,如果我知道所有数字都在 10 到 99 之间,那么使用编辑描述符会相当容易。但我没有办法提前知道这一点。

4

5 回答 5

11

这对我有用

real :: areal

然后

write(*,'(i3.3,f0.6)') int(areal),areal-int(areal)
于 2013-07-26T18:33:00.967 回答
2

可以对整数字段执行零填充,因此如果您将结果打印为两个单独的字段,您也许可以做到这一点。这是一种不太漂亮但有效的方法。Sayx是您要打印的值:

DOUBLE PRECISION x
CHARACTER*6 y

x = 123.4567

WRITE(y,'(F6.4)') x-int(x)


WRITE(*,'(I3.3,A5)') int(x), y(2:5)

y被声明为 aCHARACTER*6因为它需要保存数字的小数部分(小数点后 4 位)、前导零和小数点。如果您想显示更多小数位,这可以很容易地更改,但如果您想显示可变数量的小数位,这将更加棘手。

字段描述符的I3.3意思是“打印一个最大字段宽度为 3 的整数,并用零填充左侧,以便始终有 3 位数字”。当打印出我们y(2:5)去掉前导零的值时。

快乐编码!

于 2013-07-26T17:24:35.353 回答
2

这是我在 70 年代后期在 Commodore PET 上的 MS BASIC 中使用的技巧。代码已针对负数进行了修改。如果您希望正数有一个前导 +,只需将 signchr 的最后一个字符更改为 '+'

subroutine leadingzero(x)
   real x
   character(len=16) str
   character, dimension(3):: signchr = (/'-', ' ', ' ' /)
   write(str,'(F9.4)') 1000.0 + abs(x)
   write(*,*) signchr(int(sign(1.0,x)) + 2), str(2:) ! drop the 1
end subroutine leadingzero

program main
   call leadingzero(0.01)
   call leadingzero(0.1)
   call leadingzero(2.532)
   call leadingzero(9.9999)
   call leadingzero(9.999999)
   call leadingzero(10.987)
   call leadingzero(123.456)
   call leadingzero(0.0)
   call leadingzero(-0.01)
   call leadingzero(-0.1)
   call leadingzero(-2.532)
   call leadingzero(-9.9999)
   call leadingzero(-9.999999)
   call leadingzero(-10.987)
   call leadingzero(-123.456)
end program

编辑 - 以字符串形式返回结果

subroutine leadingzerostr(x, str_temp)
    real x
    character(*) str_temp
    character(len=10) str
    character, dimension(3):: signchr = (/'-', ' ', ' ' /)
    write(str,'(F10.4)') 10000.0 + abs(x)
    str_temp = str
    str_temp(1:1) = signchr(int(sign(1.0,x)) + 2)
end subroutine leadingzerostr
于 2013-07-26T18:24:16.460 回答
1

高性能标记方法的另一种方法是使用TLTR位置编辑描述符。首先打印带有 的浮点数Fw.d,向后移动w个位置,打印带有填充零和宽度w - d的整数,向前移动d + 1 个位置。

write (*, '(F6.3,TL6,I2.2,TR4)') f,int(f)

这种方法和高性能标记的方法存在的问题是四舍五入。以下程序演示了这一点:

program test_rounding
  double precision :: f
  f = 6 - 1D-6
  ! default compiler dependent rounding :: gfortran NEAREST
  write (*, '(F6.3,TL6,I2.2,TR4)') f,int(f)
  write (*, '(I2.2,F0.3)') int(f), f-int(f)
  write (*, '(I2.2,F4.3)') int(f), f-int(f)
  ! rounding to ZERO
  write (*, '(I2.2,RZ,F4.3)') int(f), f-int(f)
  write (*, '(RZ,F6.3,TL6,I2.2,TR4)') f,int(f)
end program
05.000          < WRONG
051.000         < VERY WRONG
05****          < EUH
05.999          < OFF BY 0.001
05.999          < OFF BY 0.001

最后一种方法可能很有趣,但它并不是真正的预期值。但是,它具有相同的精度。

以下两种方法按预期工作,但需要以尊重的准确性手动操作数字。这不是人们所期望的:

program test_rounding
  double precision :: f
  f = 6 - 1D-6
  ! manual manipulation
  write (*,'(I2.2,".",I3.3)') nint(f*1D3)/1000, mod(nint(f*1D3),1000)
  write (*,'(F6.3,TL6,I2.2,TR4)') f,nint(f*1D3)/1000
end program

两者都返回06.000

于 2020-01-27T10:41:19.480 回答
0

我不相信有一个编辑描述符可以做你想要的,但你可以用if-statement 模拟它:

if(var < 10) then
   write(*,'(a,f6.4)') '00',var
else if(var < 100) then
   write(*,'(a,f7.4)') '0',var
else
   write(*,'(f8.4)') var
endif
于 2013-07-26T16:52:45.880 回答