- ベストアンサー
Fortran において変数の定義
現在Fortranを使いプログラムをしていますが、円の面積を計算するため変数を定義しているところでおかしな問題が出てきました。円周率を定義するところで自分でつけた変数名 PAI の値が入力データと違うことに気づきました。以下のように簡単なプログラムを作って試したのですが結果は同じくおかしな値が出てきました。 IMPLICIT REAL*8(A-Z) PAI=3.14159265 WRITE(*,1)PAI 1 FORMAT(E30.22) PAUSE END 結果は 0.3141592741012573000000E+01 とディスプレイに表示され、このあとにPAIを使った計算があるならこの値で計算されます。私としては、PAI=3.14159265と出力し、計算もしたいのですが... これは FORTRAN 自体の特有の性質なのでしょうか、それともソフト、ハード的な問題なのでしょうか? 尚、変数 PAI をファイルから読み込んだり、PAI=4.0*ATAN(1.0) (PAI=3.1415926535897930 となりますが)、PAI=3.14159265D+00などにすると正確に表示、計算出来ます。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
こんにちはuni050というものです。 実際に試してみてわかった事を一つ。 i686、g77でコンパイルを行って試したところ実際にこの様になりました。で、次にalpha(OSF1)、g77で試してみたところ同じようになりました。そこで今度は、alpha、f77で試してみたら 0.3141592650000000208621E+01 となりました。そのほかにもいろいろ試してみたことから得られた結論として、数字がおかしくなるのはコンパイラの方の問題かと。 あと、ためしに double precision pai pai = 3.14159265 でg77でやってみたらうまくいきませんでした。おそらく入力する数字が単精度になっているから下の方の桁がうまく入らないのではないかと。これは推測なのであまり当てになさらずに。
その他の回答 (5)
IMPLICIT REAL*8(A-Z) より.単精度の宣言の宣言をしていますので.有効桁は7.2桁になります。 3.14159265 より.7.2桁を超える数値を指定していますから.この値は倍精度です。定数ですから.コンパイラーは7.2桁に丸めた数値を変数PAIに設定します。 (E30.22) より.E形式の出力を指定していますので.変数PAIの内容を単精度に換算して.その後に.30.22桁で表示します。 今のコンパイラーは型変換を自動でやってくれますから.このようなおかしな事になるのです(昔のコンパイラーでは型変換をせずメモリーから直接読み取るので.明らかに間違った答(0とか不の和とか)を出す)。簡単な方法としては IMPLICIT REAL*8(A-Z) を倍精度の宣言.たとえばダブルリアル(スペル忘却)宣言に直す方法があります。
お礼
いやー質問の最初に書いておくべきだったんですけど、どうしてこのような問題が起こったかというと、WARKSTATION (CPU:R10000,64bit)でコンパイル(Fortran は古い)して走らせるちゃんとPAI=3.1415926540000・・・と結果が出てくるんですよ。やっぱりbit数の関係ですかねー.(でもコンパイラは64bit対応か解らないんですけど。) IMPLICIT REAL*8(A-Z)とIMPLICIT DOUBLE PRECISION(A-Z)は何か違うのですか?どちらも同じ意味と私は思っているんですけど。 どうもありがとうございました。
- ymmasayan
- ベストアンサー率30% (2593/8599)
> これは FORTRAN 自体の特有の性質なのでしょうか、それともソフト、ハード的な問題なのでしょうか? どれでもありません。数学の問題です。つまり、2進数と10進数の間で、小数点数の変換を行なうと(ほとんどの場合)わずかな誤差が出てしまうのです。これを完璧に防ぐ方法は(特殊な方法を使う以外)ありません。FORTRANなどの技術計算用言語では、極端に言うとこれをあきらめています。倍精度を使ってもそれ以上の精度を採用しても誤差が小さくなるだけで、ゼロには決してなりません。 特殊な方法というのは10進数で計算を行なうのです。汎用の大型計算機では10進計算のハード(命令語)をもっていますし、商業計算が得意なCOBOL言語では、ハードがなくてもソフトで10進計算をやっています。 質問の答えにはならないかも知れませんが、(歯がゆい事ながら)技術計算では、色々工夫しながらFORTRANやCを使っていくしかないと思います。
お礼
確かに数学の話ですね。右辺を単精度で定義していたならこうなりますね。 10進数計算の話ですが最近は(昔からあるのかな?)BASIC にも2進数、10進数どちらでけいさんするのかを選ぶのもあるみたいですね。 どうもありがとうございました。
- a-kuma
- ベストアンサー率50% (1122/2211)
No.3 の回答に補足。 コンパイルオプションで、定数を倍精度で扱うコンパイラもある(→参考URL)ので、 そっちの方も気にして見てください。
- a-kuma
- ベストアンサー率50% (1122/2211)
> PAI=3.14159265 の右辺が *単精度* の表現であるから、なのだと思います。 コンパイラによっていろいろな表現があるのだと思いますが、例えば、参考URLに よれば、 > 倍精度(8バイト)の実数定数は,定数値_8 で与える。 とありますので、 PAI=3.14159265_8 とすると、お望みの結果になりそうです。 まずは、お手持ちのコンパイラのマニュアルでデータ型とか定数とかの項を 読むことをお勧めします。
お礼
あまりマニュアルを信用していない私ですが、のぞいてみたところ確かにそのように書いてありました。(倍精度型実数にはDをつけると) どうもありがとうございました。
- yfujii
- ベストアンサー率17% (14/80)
PAI=3.14159265 の部分ですが左辺は倍精度実数、右辺は単精度実数(REAL*4) です。 単精度実数の場合10進数にした場合有効桁数が6桁強程度しかありません。 倍精度実数は有効桁数が10進数で13桁程度ありますので代入した場合、単精 度実数で表せない部分にごみがはいります。 これを避ける為には右辺も倍精度実数にする必要があり、それが後編で試された 内容です。 FORTRANに限りませんが(C言語も同じです)、代入時の型に注意しないとこの ような事がよくおこり原因不明の精度低下ということがあります。 なれると大丈夫なのですけどね。がんばって下さい。
お礼
本当に変数の定義のときには注意が必要ですね。 今までの私のプログラムは倍精度実数にすることなく定義しているので、これから一時はそれを直すのに時間がかかりそうです。(大変だーー) どうもありがとうございます。
お礼
何かいろいろなコンパイラがあるみたいですね。 いろいろ調べてみた結果コンパイラにも「あまく」コンパイルするのもあるみたいですね。ありがとうございました。