web-dev-qa-db-ja.com

Fortranで先行ゼロを使用してフォーマットされた出力

必要に応じて先行ゼロを使用してテキストファイルに書き込む必要のある10進数がいくつかあります。私はこれについていくつかの調査を行いました、そして私が見たすべては次のような何かを示唆しています:

  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」ですが、その先頭のスペースは、.txtファイルを使用しているものを壊しているため、受け入れられません)。

15
GeneralMike

問題は、整数データ編集記述子にあります。 _I3.3_では、少なくとも3桁が必要で、フィールド幅は3桁のみです。マイナス記号の場所はありません。 _I4.3_を使用するか、Fortran 95以降では_I0.3_を使用します。

編集への回答:_I0.3_を使用してください。必要最小限の文字数を使用します。

しかし、最後に、おそらくこれが必要です:WRITE(*,'(f0.3)') VALUE

16
Vladimir F

もちろん、少し変更することで、探しているものを手に入れることができました。

  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
GeneralMike

猫の皮を剥ぐ別の方法として..データに対して算術演算を行うのではなく、次の形式で作業することをお勧めします。

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
agentp