问题 Fortran中带有前导零的格式化输出


我有一些十进制数字,我需要在适当的时候写入带有前导零的文本文件。我对此做了一些研究,我见过的所有内容都表明:

  REAL VALUE
  INTEGER IVALUE

  IF (VALUE.LT.0) THEN
    IVALUE = CEILING(VALUE)
  ELSE
    IVALUE = FLOOR(VALUE)
  ENDIF
  WRITE(*,1) IVALUE, ABS(VALUE)-ABS(IVALUE)
1 FORMAT(I3.3,F5.4)

据我了解, IF 阻止和 ABS 部件应该允许这适用于-100 <VALUE <1000的所有值。如果我设置 VALUE = 12.3456,上面的代码应该产生“012.3456”作为输出,它确实如此。但是,如果我有类似的东西 VALUE = -12.3456,我得到“(3个星号).3456”作为我的输出。我知道当星号中没有足够的字符时,通常会出现星号 FORMAT 声明,但在本例中3应该足够了(“ - ”为1个字符,“12”为2个字符)。我还没有测试过类似的东西 VALUE = -9.876,但我希望输出为“-09.8760”。

我对这是如何工作的理解有什么不对吗?或者我违反了这项技术还有其他一些限制吗?

更新:好的,我已经对此进行了更多研究,它似乎是一个负值和一个组合 I3.3 格式。如果VALUE为正,我有 I3.3,它将按预期放置前导零。如果VALUE为负数且我只有 I3 作为我的格式,我得到正确的值输出,但它会在负号之前用空格填充,而不是在负号之后用零填充(所以-9.8765输出为“-9.8765”,但是那个领先的空间打破了我的' m使用.txt文件,所以这是不可接受的)。


12873
2018-01-29 17:36


起源

为什么选择downvote? - GeneralMike
作为一个kludge,你可以把写入if,打印一个' - '作为一个字符串的neg case,然后是abs(int)格式化你喜欢。我希望格式专家能够提出一个合适的解决方案。 - agentp
@george:哈哈,当你发布这个=)时,我只是写了我的答案。 - GeneralMike


答案:


问题在于整数数据编辑描述符。同 I3.3 你需要至少3位数,字段宽度只有3.没有减号的地方。使用 I4.3 或者,在Fortran 95及以上版本中, I0.3

回答你的编辑:使用 I0.3,它使用必要的最少字符数。

但最后,你可能想要这个: WRITE(*,'(f0.3)') VALUE


12
2018-01-29 18:14



啊,所以I3.3指定每个字符需要是一个数字,减号不允许在那些点。我现在明白了。是的, I0.3将要做的伎俩。谢谢!! - GeneralMike
在花了太多时间之后,我发现我的编译器也支持f0.n在最小字段宽度中打印一个浮点值,我认为这是他真正想要的。我不知道这个(或I0)是标准的还是它的版本。 - agentp
你是对的,我没有充分研究其余的问题。它出现在Fortran 95中。 - Vladimir F
@george:呃,希望在我开始这一切之前我已经注意到了。 F0.3正是我从一开始就在寻找的东西,但是我发现其他网站都说不存在这样的东西(它们一定不能更新吗?或者他们说这是F77的唯一途径可能吗?w / e),分成整数和小数部分是唯一的方法。更重要的是,直到我花了半天更新我的所有代码之后,我才真正看到这篇文章 I0.3,F5.4。好吧,我想将来参考。这就是我相信我在互联网上读到的一切...... - GeneralMike


当然,我可以通过改变它来获得我正在寻找的东西

  REAL VALUE
  INTEGER IVALUE

  IF (VALUE.LT.0) THEN
    WRITE(*,1) FLOOR(ABS(IVALUE)), ABS(VALUE)-FLOOR(ABS(VALUE))
1   FORMAT('-',I2.2,F5.4)    
  ELSE
    WRITE(*,2) FLOOR(VALUE), ABS(VALUE)-FLOOR(BS(VALUE))
2   FORMAT(I3.3,F5.4)
  ENDIF

但是这感觉很笨拙,实际上我会尝试在同一行中写出多个值,这将导致非常混乱 IF 块或复杂的光标移动,如果可能的话我想避免。


0
2018-01-29 18:19





作为皮肤猫的另一种方式..我宁愿不对数据进行算术运算,只需要处理格式:

character*8 fstring/'(f000.4)'/
val=12.34
if(val.gt.1)then
    write(fstring(3:5),'(i0)')6+floor(log10(val))
elseif(val.lt.-1)then
    write(fstring(3:5),'(i0)')7+floor(log10(-val))
elseif(val.ge.0)
    write(fstring(3:5),'(i0)')6
else
    write(fstring(3:5),'(i0)')7
endif
write(*,fstring)val

只是为了与现代fortran一起使用,它支持角色功能,你可以在一个函数中滚动它,最后得到一个这样的结构:

write(*,'('//fstring(val1)//','//fstring(val2)//')')val1,val2

0
2018-01-29 19:07