我需要从Fortran程序输出一些浮点数。让我们说最大数字可能是999.9999,它们都是非负数。我需要在所有小于100的数字前面进行零填充。
例如,如果我有25.6893782,245.354567和1.2345678,我需要以类似
的形式打印出来025.6894
245.3546
001.2346
我该怎么做?使用T
编辑描述符会相当容易,例如,我知道所有数字都在10到99之间,就像那样。但是我没办法提前知道。
答案 0 :(得分:11)
这对我有用
real :: areal
然后
write(*,'(i3.3,f0.6)') int(areal),areal-int(areal)
答案 1 :(得分:2)
可以对整数字段执行零填充,因此如果您将结果打印为两个单独的字段,您可能能够实现它。这是一种不太漂亮的方式,但有效。说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)
去掉前导零。
快乐的编码!
答案 2 :(得分:1)
这是我在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
答案 3 :(得分:1)
High Performance Mark方法的另一种方法是使用TL
和TR
位置编辑描述符。首先使用Fw.d
打印浮点,向后移动 w 位置,打印填充零和宽度为 w − d 的整数,移动 d + 1 < / em>向前定位。
write (*, '(F6.3,TL6,I2.2,TR4)') f,int(f)
此方法和High Performance Mark的方法存在的问题是舍入。下面的程序演示了这一点:
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
答案 4 :(得分:0)
我不相信有edit descriptor符合您的要求,但您可以使用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