我有一些浮点数需要从Fortran程序输出。假设最大值可能为999.9999,它们都是非负的。对于所有小于100的数字,我需要在前面填充零。
例如,如果我有25.6893782、245.354567和1.2345678,我需要以以下形式打印出它们:
025.6894
245.3546
001.2346
我该如何做到这一点?如果我知道所有数字都在10到99之间,那么使用T
编辑描述符就相当容易了。但是事先我无法知道这一点。
我有一些浮点数需要从Fortran程序输出。假设最大值可能为999.9999,它们都是非负的。对于所有小于100的数字,我需要在前面填充零。
例如,如果我有25.6893782、245.354567和1.2345678,我需要以以下形式打印出它们:
025.6894
245.3546
001.2346
我该如何做到这一点?如果我知道所有数字都在10到99之间,那么使用T
编辑描述符就相当容易了。但是事先我无法知道这一点。
这对我有效
real :: areal
然后
write(*,'(i3.3,f0.6)') int(areal),areal-int(areal)
对于整数字段可以进行零填充,因此如果将结果打印为两个单独的字段,则可能会使其发生。这里有一种不太美观但有效的方法。假设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
被声明为 CHARACTER*6
,因为它需要容纳您的数字的小数部分(4位小数),一个前导零和一个小数点。如果您想显示更多的小数位数,这很容易改变,但如果您想显示可变数量的小数位数,则会更棘手。
I3.3
字段描述符的意思是“打印最大字段宽度为3的整数,并在左侧填充零,以确保始终有3个数字”。在打印值时,我们将使用 y(2:5)
来去除前导零。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
signchr(int(sign(1.0,x)) + 2), str(2:)
,例如,str_temp
,它是一个长度为 0000.0000
的 字符类型
? - user4372504str_temp
函数。 - user4372504TL
和TR
位置编辑描述符来代替高性能标记的方法。首先使用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
我不认为有一个编辑描述符可以做到你想要的,但你可以用一个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
write
语句会将其格式化为“10.0000”,从而产生“0010.0000”的输出,而不是期望的“010.0000”吗? - Eric Postpischil010.0000
,但如果你有 9.9999
,它将会输出 009.9999
。 - Kyle Kanosvar < 10
,导致写入“00”后跟着“10.0000”吗? - Eric PostpischilREAL
)导致的。如果我使用9.99999
,它会返回00******
。 - Kyle Kanos
2.999999999999
这样的数字时会失败。由于四舍五入,这将变得尴尬。 - kvantour