Floating point 如何用前导零填充Fortran浮点输出?

Floating point 如何用前导零填充Fortran浮点输出?,floating-point,formatting,fortran,Floating Point,Formatting,Fortran,我有一些浮点数需要从Fortran程序中输出。假设最大值为999.9999,它们都是非负数。我需要在所有小于100的数字前面填充零 例如,如果我有25.6893782、245.354567和1.2345678,我需要以如下形式打印它们 025.6894 245.3546 001.2346 我该怎么做?例如,如果我知道所有的数字都在10到99之间,那么使用T编辑描述符就相当容易了。但是我没有办法提前知道这一点。我不相信有一种方法可以满足您的要求,但是您可以用if-语句模拟它: if(var &l

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

例如,如果我有25.6893782、245.354567和1.2345678,我需要以如下形式打印它们

025.6894
245.3546
001.2346

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

我不相信有一种方法可以满足您的要求,但是您可以用
if
-语句模拟它:

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
如果(var<10)那么
写入(*,'(a,f6.4)'00',变量
否则,如果(var<100),则
写入(*,'(a,f7.4)'0',变量
其他的
写入(*,'(f8.4)')变量
恩迪夫

可以对整型字段执行零填充,因此,如果将结果打印为两个单独的字段,则可以实现零填充。这里有一种方法不太漂亮,但很有效。假设
x
是要打印的值:

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
被声明为
字符*6
,因为它需要保存数字的小数部分(小数点后4位)、前导零和小数点。如果您想显示更多的小数位数,则可以很容易地更改此设置,但如果您想显示可变的小数位数,则此设置会更加复杂

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


快乐编码

这是我70年代末在MS BASIC中对Commodore宠物使用的一个技巧。该代码已修改为负数。如果您希望正数有一个前导+,只需将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
这对我有用

real :: areal
然后


方法的另一种方法是使用
TL
TR
位置编辑描述符。首先用
Fw.d
打印浮点,向后移动w个位置,用填充零和宽度w打印整数− d、 向前移动d+1位置

write (*, '(F6.3,TL6,I2.2,TR4)') f,int(f)
这个方法和have方法的问题是舍入。以下程序演示了这一点:

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

两者都返回
06.000

如果一个值接近10,比如9.999999,
语句会将其写入格式为“10.0000”,从而产生“0010.0000”的输出,而不是所需的“010.0000”?它将给出所需的
010.0000
,但如果您有
9.9999
,它将输出
009.9999
。这是如何工作的?9.9999999是否会通过测试
var<10
,导致在“00”后面写上“10.0000”?我刚刚测试了它&它就是这样工作的;我认为这是由于精度(使用
REAL
)。如果我使用
9.99999
,它会返回
00******
。我找到了类似的方法。你和我基本上都在做高性能马克所做的事情,但他的方式要紧凑得多。谢谢你的帮助。我看到了高性能Mark的修复,我同意。我不知道“0”宽度说明符,但它是一个更好的解决方案。很高兴能帮上忙。在继续思考的同时,我想出了这样的主意,但你的方式要优雅得多。谢谢。由于四舍五入,此方法在出现
2.9999999999999
等数字时将失败。如果值为负数,您能否提供解决方案?您希望得到什么样的结果?它为-ve打印-000.01,为+ve打印000.01。是否有机会展示我们如何编写
signchr(int(sign(1.0,x))+2),str(2:)
,例如,
stru temp
,这是一种长度为
0000.0000
字符类型
?结果是空白字符。尝试使用
str\u temp
类似字符结果的函数。
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