Floating point 如何用前导零填充Fortran浮点输出?
我有一些浮点数需要从Fortran程序中输出。假设最大值为999.9999,它们都是非负数。我需要在所有小于100的数字前面填充零 例如,如果我有25.6893782、245.354567和1.2345678,我需要以如下形式打印它们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
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