• ベストアンサー

fortranで図形の面積を求めるには?

今fortranのプログラムをやっているのですが、 図形の面積を求めたいのですがどうやったらいいのでしょうか? とりあえず小さな区間に区切って足し算を行うようにしているのですが、うまく動きません・・・。 DOループをまわし過ぎなのでしょうか??? 一応下にプログラムの一部を書いておきます。 DO 444 J= 1,5000 T=FLOAT(J)*0.1 IF (T.GE.281)THEN GL3 = -0.01105*T+4.104972 ELSE    GL3 = -0.01105*T-2.1050 ENDIF     ・     ・     ・ 444 CONTINUE 誰か助けてください! 宜しくお願いします。

  • 4436
  • お礼率0% (0/40)

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.6

質問者本人抜きの議論は、ここでは御法度ですが、質問者の理解の助けに なると信じ、実数の比較の話に決着をつけます。 ubonoti01 さんの理解は、理由を抜きに「実数の比較が危ないらしい」と いう風になっているのがまずい。 今回の質問のプログラム DO 444 J= 1,5000  T=FLOAT(J)*0.1  IF (T.GE.281)THEN であれば、EQUAL を含めて、問題なく判定されます。問題が出るのは、 T = 0.0 DO 444 J = 1, 5000  T = T + 0.1  IF (T .GE. 281.0) THEN となっている場合。でも、同様の書き方でも T = 0.0 DO 444 J = 1, 5000  T = T + 0.5  IF (T .GE. 281.0) THEN であれば、問題なく動く計算機が *多い* です。 どうしてこんなことになるかというと、(Fortran で扱う)実数が二進数で 表現されている(正確にいえば、二進数の指数表現)からです。 0.1 は、十進数で書くと切りが良いですが二進数で表現すると無限小数に なります。だから二進数の世界では   0.1 × 10 ≠ 0.1 + … + 0.1 (10回足す) となってしまいます。 先ほど例に出した 0.5 は、二進数の世界でも無限小数ではありません。 だから、   0.5 × 10 = 0.5 + … + 0.5 (10回足す) が成立します。 で、このへんの話は「実数を二進数で表現すること」の問題なので、 Fortran 固有の問題ではなく、C でも同様の問題を抱えます。 bob> 実数の大小比較に信頼性がない のではなく、演算結果が等しいかどうかを判断するときに実数演算の 誤差を考慮しなくてはいけない、と言うことです。 ubonoti01> IF (J.GE.2810)THEN の方が好ましい とあるのは、その「考慮」のやりかたのひとつです。 (補足 その1) 先程、0.5 を足して行くケースで「問題なく動く計算機が *多い* です」と いう表現を使いました。それは、実数の表現が二進数表現ではない計算機が あるからです。いわゆる IBM Format と呼ばれる実数表現では 16進数の 指数形式で表現されます。 なので、多分 0.5 では 0.1 と同様の問題が出るはずで、0.0625 (1÷16)なら 問題は発生しません。 (補足 その2) COBOL では、ふつう実数は BCD コードで桁数を指定して扱います。なので、 オーバフローやアンダーフローが無いように桁を決めてあげれば、こういった 問題は出ません。

その他の回答 (5)

  • bob
  • ベストアンサー率50% (52/103)
回答No.5

便乗質問になってしまいますが、私は基本的にCプログラマでFortranでの計算はあまりやったことがないのでFortran独特のくせは確かによく知らないので、一応質問させていただきます。 実数の大小比較に信頼性がないということは、そのままとるとFortranは実数が使えないというのと同義です。主に科学技術計算に使われてきたFortranの歴史からいくとちょっと信じがたいのですが、これは本当なのでしょうか?

  • ubonoti01
  • ベストアンサー率20% (43/211)
回答No.4

再度ubonoti01です。 わたしがIF (T.GE.281)THEN は、IF (J.GE.2810)THEN の方が好ましいと申したのは、 ・IF文の中でREAL同士を比較するのは危険と言う意味です。IF文の中での値の比較はINTEGER同士の比較であるべきです。出所が別のREAL同士の比較では、本来一致する筈が真でなく偽と判定されるケースが多いからです。これはコンピュータ内部での数値の扱いに起因します。

  • bob
  • ベストアンサー率50% (52/103)
回答No.3

やはり、最初に問題の説明が不足していることを指摘しておきます。 この質問内容では推測による回答しかできません。 で、推測に基づく回答ですが、やっていることは数値積分ですね。おそらく1次式で表わされる2直線とx軸(t軸)とy軸(gl3軸)で囲まれる部分の面積を求めようとしているのだと思われます。 で、予想される問題点ですが、多分変数Tに掛けている定数-0.1105のうちどちらか(多分後者)は符号が逆でしょう。切片も-2.1050ではなくて2.1050では? if分岐の条件についてですが、ubonoti01さんと意見が割れますが、この場合は積分変数による分岐なのでTで分岐する方で良いと思われます。 おそらく意味的にもっといいのは各式を関数化しておいて、IF([2式].GE.[1式])THENと書いてしまうことです。計算量は若干多くなりますが、281という一見意味不明なパラメータを直接書く必要はなくなります。 そして、おそらく一番決定的な問題は積分の和をとってないことです。先頭にS=0をいれて、CONTINUEの前にS=S+GL3を入れるか、GL3を初期化しておいて2つの式をGL3=GL3+...にする必要があると思われます。 最後に、ループの終了条件がJ=5000というのはちょっと怪しいと思われます。この時GL3はゼロを割り込んでいます。おそらく3715以下の数値になると思われます。

  • ubonoti01
  • ベストアンサー率20% (43/211)
回答No.2

もう少し背景なり状況なりを示した質問をすべきと思いますが・・・・・・。プログラムだけを見た範囲では、a-kumaさんのご指摘のほかに、 IF (T.GE.281)THEN は、 IF (J.GE.2810)THEN の方が好ましいと思います。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

どう上手くいかないんですかね? コンパイルができない、期待している数字と結果が違う、計算に時間がかかり 過ぎる、etc ... このコードの断片だけを見ると、コンパイルはできそうだし、ぎざぎざの のこぎりのような形の面積を求めたいのかな、位しか想像つきません。 もしそうだとしたら、GL3 の初期化がされていないところと、Tの判断条件 のところが怪しいかな、くらいを思い付きます。    GL3 = 0.0 ← ★ 必要なし?    DO 444 J= 1,5000     T=FLOAT(J)*0.1          IF (T.GE.281)THEN ← ★ 281? 28.1? 不等号の向きは合ってる?      GL3 = -0.01105*T+4.104972 ← ★ 右下がりで     ELSE      GL3 = -0.01105*T-2.1050 ← ★ こっちも右下がり?     ENDIF ← ★ 終わっちゃっていいの?         ・ ← ★ 続いているみたいだけど         ・         ・  444 CONTINUE ぎざぎざな形の面積だったら、こんな感じになるんじゃない? IF (T .LT. 100.0) THEN  GL3 = ... ELSE IF (T .LT. 200.0) THEN  GL3 = ... ELSE IF (T .LT. 300.0) THEN  ・  ・ ENDIF

関連するQ&A

  • FORTRAN

    FORTRANについて聞かせてください。 WRITE(*,*) 'A= READ( *,*) A Aの値を0~0.15の範囲で0.01刻みで増やしていって実行したいのですが,どのようにプログラムを作成すればいいですか?? DOループだと思うのですが,あってますか? 分かる方いらっしゃったらお願いします。 FORTRANについてお勧めの初心者用ホームページがあればおしえてくださると助かります。

  • FORTRAN→Cに翻訳

     どなたか、次のFORTRANのプログラムを、Cに、翻訳して頂けないでしょうか。C++ではなく、Cです。ANSI準拠のCでお願いします。  プログラムの内容は、最小二乗法による計算プログラムです。MS-DOS Ver3.3~6.0の頃の、MS FORTRANコンパイラ仕様のものです。その頃持っていたFORTRANの本も処分してしまい、今からFORTRANを学びなおすのにも多大な労力と時間がかかりそうなので、Cに翻訳して頂ければ大変ありがたいです。よろしくお願いします。 (“□”はタブ) ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ C□LEAST SQUARE APPROXIMATION □PROGRAM MAIN9 □DIMENSION X(100),Y(100),S(0:18),T(0:9),SM(10,10),TV(10),AV(10) □WRITE(*,*) 'N ?' □READ(*,*) N □WRITE(*,*) 'x1,x2,..,xn ?' □READ(*,*) ( X(I),I=1,N ) □WRITE(*,*) 'y1,y2,..,yn ?' □READ(*,*) ( Y(I),I=1,N ) □WRITE(*,*) 'M ?' □READ(*,*) M □DO 110 K=0,M*2 □□VS=0. □□DO 100 I=1,N □100□VS=VS+X(I)**K □□S(K)=VS □110□CONTINUE □□DO 130 K=0,M □□□VS=0. □□□DO 120 I=1,N □120□VS=VS+Y(I)*X(I)**K □□□T(K)=VS □130 CONTINUE □□DO 140 I=1,M+1 □□□DO 140 J=1,M+1 □□□□K=I+J-2 □□□□SM(I,J)=S(K) □140 CONTINUE □□DO 150 I=1,M+1 □150 TV(I)=T(I-1) □□CALL SIMULE( AV, SM, TV, M+1 ) □□DO 160 I=1,M+1 □160 WRITE(*,1000) I-1,AV(I) □1000 FORMAT(1H ,'A',I1,'=',F10.5) □□STOP □□END ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆

  • fortran77で複数のファイルの読み込み

    fortran77で複数のファイルの読み込み 現在fortran77のプログラムを勉強しております。 ファイルが複数あり、すべてのファイルを読み込みたいのですが、ファイルの数がたくさんあるため、プログラムの行数が多くなってしまいます。 do ループで次々とファイルを開くプログラムを考えているのですが、思いつきません。 どなたか考え方でもいいので、教えてください。 ちなみに私が考えたプログラムは、 open(10,file='C:\FORTRAN\100.txt',status='old') open(11,file='C:\FORTRAN\121.txt',status='old') open(12,file='C:\FORTRAN\144.txt',status='old') open(13,file='C:\FORTRAN\169.txt',status='old') open(14,file='C:\FORTRAN\196.txt',status='old') open(15,file='C:\FORTRAN\225.txt',status='old') ・・・。 これを do ループで次々に開くことを考えると、 character*3 A(10) do 100 i=1,10 A=i*i open(i,file='C:\FORTRAN\A.txt',status='old') 100 continue ・・・ みたいな感じです。 ' 'の中の一部だけを変えたい場合のcharacter 文の使い方がいまいちよく分かりません。

  • Fortranについて質問です。

    プログラムソースの中で ----------------------- Real*8 A(10,10) Do 30 i = 1, 5 Do 40 j = 1,5 A(i,j)=0.0D0 40 Continue 30 Continue ------------------------ というのは、 配列A(i,j)にどんな値を入れるのですか? すべて0が入るということですか? 教えてください><

  • fortranのプログラム

    fortranのプログラム 現在、fortranの勉強をしております。 そこで、質問があるのですが、 ある関数f(x,y,z)の座標(x,y,z)の値がデータとして与えられているとき、 S=10+f をfortranで計算したいと考えております。 ただ、関数fは複数(f1、f2、f3)あり、次々とfに代入してSを計算したいのですが、どのようにプログラムしたらいいか思いつきません。 どなたか、ヒントだけでもいいので、教えてください。 ちなみに、私が考えたプログラムは(下のプログラムはポイントだけ書いてあります。endやその他関係ないと思われるところは省いております。) do 100 k=1,3 S=S+fk(x,y,z) continue function f1 f1(s,t,u)=・・・ return end f2(s,t,u)=・・・ return end 使用しているバージョンは、fortran77(本当は90を使っているのですが、77だけで書いています)です。

  • fortran 繰り返し計算の問題

    皆様、先日、色々教えていただきまして、どうも有り難うございました。特にfunoe様からのお答えがとても助かりました。ただし、どうも一つの条件だけが満足されると、計算が終了に行ってしまいました。 再度問題を整理したうえで、質問させて頂けませんでしょうか。 (例えば、電気回路の例) do j=1, n  Ra(j),Qi(j) !予めある回路に初期の抵抗値と得たい電流値を与える end do Tr=1.0 / / / 10 continue / do j=1,n Vi(j)=V/Ra(j) !Vを一定値とする / do 100 j=1, n if (abs(Vi(j)-Qi(j)) > 0.1) then Ra(j)= Ra(j)+ Tr goto 100 !nまで繰り返し else goto 500 !終了する end if 100 continue 1000 continue goto 10 !戻り、再計算 500 continue stop end ***************************************** 例えば(n=10),予め与えた10本の回路のQi値がすべて同じな場合には、上記のプログラムでは、うまく行っていますが、10本回路のQi値が違い場合には、そのうち1本回路の値が満足されると、終了していしまいました。  また、elseの前に、 「elseif (Vi(j)-Qi(j) <= 0.1) then Ra(j)= Ra(j) 」 を追加すると、ループから抜き出せなくなりました。  また、初期条件としては、始めに小さいRaを与えて、最初計算したViがQiより大きくして、それから、Raを増やして、ViをQiに近づけるように考えていますが、なかなかうまく行っていないのです。また、回路ですので、一箇所のRaを変更すると、当然他の値にも影響を与えます、ここには難しくと思っております。  皆さまに、教えていただければ、幸いなことと思います。よろしくお願い致します!<!!^!!)。

  • FORTRANの動的割り当てについて

    今、FORTRANでg95でプログラムを作っているのですが、動的割り当てで理解出来ない現象が起きたので質問させていただきます。 real(8),dimension(:,:,:),allocatable :: a と三次元の動的配列aを定義し allocate(a(0:10,0:10,0:10)) としています。 ここで、外部のファイルから各成分0~10の配列の所に値を読み込ませます。 私の理解では、これは0~10の添字までしか扱えないものと思っていたのですが、write文でa(11,11,11)という要素を書かせてみると、実際に値が出力されてしまいます。動的割り当てとはそういうものなのでしょうか。 また現在作っているプログラムではこれが値を持っているとまずいので、doループで11の値のところだけをif文で0にしようと試みたのですが、そのif文を反映してくれません。 (つまり do i=0.11 do j=0,11 do k=0,11 if (i==11.or.j==11.or.k==11) then .・・・ の時、・・・のところで0にしようしてもそれが反映されない) 始めはコードが間違っているのかと思いましたが、doループの10の値のところを同様に0にしてみたら成り立っていました。 (つまり do i=0,10 do j=0,10 do k=0,10 if (i==10.or.j==10.or.k==10) then ・・・ の時、・・・のところで0にしようとするとそれが反映される) これはやはり定義してないa(11,11,11)が出力されることと関係があるのでしょうか。 初歩的な質問かもしれませんが、よろしくお願い致します。

  • fortranとVBAのdo文

    fortranをBVAのプログラムに直す作業をしています。 プログラムが不慣れなもので、基本的なことかもしれませんが書き込みます。 fortranにて do 10 i=1, n call SET(IX, i, x(i)) 10 continue ここでn、IXは整数で、サブルーチンSETで作業はします。 これをVBAで書き直すとどのようにあらわされるのでしょうか。 よろしくお願いします。

  • fortranの関数?

    fortranに関する質問です. あるプログラム例(おそらくfortran77で記述されている) で理解できないところがあり質問しました. BFUNC(S) = S とあるのですが,これはどういう意味なのでしょうか. BFUNCについて調べてもわからず,行き詰っています. プログラム中の後に S = FLOAT(J) / FLOAT(JMAX) E = BFUNC(S) という記述があります. ファンクション関数のようなものかとも 思いましたが,そのような設定に関する記述も特に見当たらず・・・ 何か77特有の組み込み関数とかでしょうか. 情報が少なくて意味不明かもしれませんが, 本当にここ以外では出てきません. また,S,Eともに型宣言等もありません. もしわかる方,おられましたらお教えください. よろしくお願いいたします.

  • fortran  繰り返しループから抜きたい

    10 continue   :   :   :  do 100 i=1,10 if (abs(x (i)-y(i)) .lt. 1.0) then r= r + dr goto 100 else goto 1000 end if 100 continue :   : : 1000 contiue end   すべての条件(i=1~10)が満足されたら、ループから抜きたいのですが、出来ませんでした。   教えて頂けませんでしょうか?よろしくお願しますね!*<>*!

専門家に質問してみよう