fortranでのプログラムで最大値を計算する方法

このQ&Aのポイント
  • fortranでプログラムを作成して、関数の最大値を計算する方法について質問があります。
  • 質問者は、関数の最大値を求めるために「func」関数を使用していますが、正しい結果が得られないようです。
  • 質問者は、関数内の条件分岐部分に問題があるのではないかと考えていますが、具体的な原因がわかりません。
回答を見る
  • ベストアンサー

fortranでのプログラムについて

初歩的な質問失礼します func = x**3-3*(x**2)-2*x+14 に対して real function ymax( minx, maxx) real, intent(in) :: minx,maxx real :: mx1,mx2 mx1 = (6.0+sqrt((-6.0)*(-6.0) - 4.0*3.0*(-2)))/(3.0*2.0) mx2 = (6.0-sqrt((-6.0)*(-6.0) - 4.0*3.0*(-2)))/(3.0*2.0) ! mx2は極大 mx1は極小 if (minx <= mx2 .and. mx2<maxx ) then  if (func(maxx)<func(mx2) .and. func(minx)<func(mx2)) then   ymax=func(mx2)  elseif (func(mx2)<func(maxx) .and. func(maxx)>func(minx)) then   ymax=func(maxx)  else  ymaxx = func(minx) endif else  if (func(minx)>func(maxx)) then   ymax=func(minx)  else   yamx=func(maxx)  endif endif end function ymax こういう感じで関数の最小最大を決めてグラフを画面上に変換して表示しようとするのですがどうも最大値がうまく計算されません。 どこに問題があるのでしょうか?

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

  • ベストアンサー
回答No.3

> if (func(maxx)<func(mx2) .and. func(minx)<func(mx2)) then >  ymax=func(mx2) > elseif (func(mx2)<func(maxx) .and. func(maxx)>func(minx)) then >  ymax=func(maxx) > else > ymaxx = func(minx) >endif でymaxx= ... となっているのが気になる。

ts11922960
質問者

お礼

他の場所にあったタイプミスが原因でした…。 何度も見直したつもりでしたがこんな初歩的なミスで申し訳ないです。 本当にありがとうございました。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

なんとなく implicit none してないのが敗因のような気がする.

ts11922960
質問者

お礼

何度も回答頂いて本当にありがとうございました。 もっとしっかり練習してきます(・∀・)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「どうも最大値がうまく計算されません。」とは, 具体的にはどのように「うまく計算されない」のですか? あと, プログラムにコメントがほしい.... 「こういう感じ」というのをもっときちんと書いてほしいなぁ....

ts11922960
質問者

補足

すいませんあんまり長いと見づらいかと思い省いてしまってました…。 ! 関数を決定する real function func(x) real, intent(in) ::x func = x**3-3*(x**2)-2*x+14 return end function func ! yの最大値を設定する real function ymax( minx, maxx) real, intent(in) :: minx,maxx real :: y1,y2,y3 real :: mx1,mx2 ! func(x)の微分関数=0 の解 =1±±√15/3=1±1.2 くらい mx1 = (6.0+sqrt((-6.0)*(-6.0) - 4.0*3.0*(-2)))/(3.0*2.0) mx2 = (6.0-sqrt((-6.0)*(-6.0) - 4.0*3.0*(-2)))/(3.0*2.0) ! mx2が極大 mx1が極小 !極大値が区間に入ってるか? ! 入っている if (minx <= mx2 .and. mx2<maxx ) then  if (func(maxx)<func(mx2) .and. func(minx)<func(mx2)) then   ymax=func(mx2) elseif (func(mx2)<func(maxx) .and. func(maxx)>func(minx)) then ymax=func(maxx) else   ymaxx = func(minx) ! func(minx) func(maxx) func(mx2) の最大値が最大値 endif ! 入っていない else if (func(minx)>func(maxx)) then   ymax=func(minx) else   yamx=func(maxx) ! func(minx) func(maxx) の最大値が最大値 endif endifend function ymax ! yの最小値を設定する real function ymin( minx, maxx) real, intent(in) :: minx,maxx real :: y1,y2,y3 real :: mx1,mx2 mx1 = (6.0+sqrt((-6.0)*(-6.0) - 4.0*3.0*(-2)))/(3.0*2.0) mx2 = (6.0-sqrt((-6.0)*(-6.0) - 4.0*3.0*(-2)))/(3.0*2.0) ! 極小値は区間に入ってるか? ! 入っている if (minx <= mx1 .and. mx1<maxx) then if (func(mx1)<func(minx) .and. func(mx1)<func(maxx)) then ymin = func(mx1) elseif (func(mx1)>func(minx) .and. func(minx)<func(maxx)) then ymin = func(minx) else ymin = func(maxx) ! func(minx) func(maxx) func(mx1)の最小値が最小値 endif ! 入っていない else if (func(minx)<func(maxx)) then ymin = func(minx) else ymin = func(maxx) ! func(minx) func(maxx)の最小値が最小値 endif endif end function ymin ! 画面上のy座標に変換 function transy(y,MINY,MAXY) real,intent(in) :: MINY, MAXY real,parameter :: CRTMINY=23.0, CRTMAXY=1 real,intent(in):: y transy = (CRTMAXY-CRTMINY)/(MAXY-MINY)* (y-MINY) +CRTMINY return end function transy このプログラムに対して 描画部内で iy = transy(y,miny,maxy) としたところ、正と負の数、負の数二つ、正の差の小さい二数を入力した時は正しく動くのですが、 正の3以上離れた数2つを入力したときiyが23を超えてしまいエラーが出てしまいます。 またyの値自体は正しく計算されているのに、ymaxを表示したときに ymax=0.0000000E+00 となってしまいます。 至らない所が多くて恐縮ですが、もしよろしければ回答お願いします。

関連するQ&A

  • fortran 固有値を求めるプログラム

    2x2の実行列の固有値を求めるモジュール関数の中で、d > 0 のときに出てくる sign(squt(d), -b)の値が示す意味と eval(2) = cmplx(c/e,0.0d0) でなぜ c/eの値が入るのかがわかりません。教えて下さい。よろしくお願いします。 プログラム module subprogs implicit none contains function eval2x2mat(a) result(eval) real(8), intent(in) :: a(:,:) complex(8) eval(2) real(8) b, c, d, e if (size(a,1) /= size(a,2)) stop ' not square ' if (size(a,1) /= 2) stop ' not 2x2 matrix ' b = -0.5d0*(a(1,1)+a(2,2)) c = a(1,1)*a(2,2)-a(1,2)*a(2,1) d = b**2-c if ( d < 0.0d0 ) then eval(1) = cmplx(-b,sqrt(-d)) eval(2) = conjg(eval(1)) else if ( d > 0.0d0 ) then e = -b+sign(sqrt(d),-b) ←ここの部分 eval(1) = cmplx(e,0.0d0) eval(2) = cmplx(c/e,0.0d0) else          ↑ここの部分 eval(1) = cmplx(-b,0.0d0) eval(2) = eval(1) endif end function eval2x2mat end module subprogs program main use subprogs implicit none real(8), allocatable :: a(:,:) integer :: n = 2 allocate(a(n,n)) a(1,1:2) = (/-1,1/) a(2,1:2) = (/-1,-1/) write(*,*) a(:,:), eval2x2mat(a) end program main

  • fortran cosθをベクトリから求めるプログラム

    ベクトルからcosθを求めるペログラムを作ってみたのですが、実際計算した値と実行結果の値が一致しないのですが。プログラム上に問題があるのでしょうか?教えて下さい。よろしくお願いします。 module subprogs implicit none contains function vec_cos(a,b) result(vcos) real(8), intent(in) :: a(:), b(:) real(8) ab, vcos if (size(a) /= size(b)) stop ' er : size(a) /= size(b) ' ab = dot_product(a,a) * dot_product(b,b) if (ab == 0.0d0) then vcos = 0.0d0 else vcos = dot_product(a,b)/sqrt(ab) endif end function vec_cos end module subprogs program main use subprogs implicit none real(8) :: x(1:2) = (/1.2d0, 3.4d0/), y(1:2) = (/5.6d0, 7.8d0/) write(*,*) 'cos = ', vec_cos(x,y) end program main 実行結果 cos = 0.9601163787292428

  • fortran90 引数で渡された関数の呼び出し

    fortran90を始めて間もない者です。 メインプログラムより呼び出しているサブルーチンにユーザ関数を渡しています。 このサブルーチンを自前で作成するのが目的です。 引数で受け取った関数を、自前の別関数より呼び出すにはどうしたら良いでしょうか。 Cであれば関数のポインタをグローバルな変数にセットしてやれば可能だと思いますが・・・ !-------------------------------- subroutine sub(func1, a) real::a interface real function func1(x) real::x end function func1 real function func2(x) real x end function func2 end interface call sub2(func2, a) write(*,*) a return end subroutine sub !-------------------------------- real function func2(x) real::func2, x ! ここでfunc1を呼び出したい ! func2=func1(x) end function func2 !-------------------------------- subroutine sub2(funca, a) real::a interface real function funca(x) real::x end function funca end interface a=funca(10.) return end !-------------------------------- program main external func real a call sub(func, a) write(*,*) a end program !-------------------------------- function func(x) real func, x func=2.*x*x end function func

  • fortran if文

    以下のコードで、xとthetaに5,5と入力しても、出力が5となってしまいます。500になってほしかったんですが・・・ どこが悪いのか教えて下さい。 ----------------------------------------------- read(5,*)x,theta if(0.0d0.LE.x.LE.4.0d0) then eta=theta go to 20 else if(4.0d0.LT.x.LT.7.0d0) then eta=100.0d0*theta go to 20 else if(7.0d0.LE.x.LE.10.0d0) then eta=sqrt(3.0d0*sqrt(2.0d0))*theta go to 20 end if 20 write(6,30) eta 30 format(F10.5) stop end -----------------------------------

  • mの平方根の連分数展開なのですがうまく動きません。

    subroutine keisan(m) integer a,a0,n,i,m real t,X,Y,Z t=sqrt(real(m)) a0=int(t) write(*,*) 'a0=',a0 a=a0 X=1 Y=0 Z=1 do 10 n=1,20 if (Z==0.0) exit X=X*Z Y=Z*(-Y+real(a)*Z) Z=X*X*real(m)-(real(a)*Z-Y)**2 do 100 i=1,X if(real(i)==X) then X=X else if(((mod(int(X),i))==0).AND.((mod(int(Y),i))==0).AND.((mod(int(Z),i))==0)) then X=X/real(i) Y=Y/real(i) Z=Z/real(i) else X=X endif endif 100 continue a=int((X*t+Y)/Z) write(*,*) 'a',n,'=',a 10 continue end subroutine サブルーチンのみ載せてますけど・・・・どうなのでしょう??

  • fortran 乱数を用いてcosθをベクトリから求めるプログラム

    乱数を配列に格納してcosθをベクトルから求めるプログラムを書いてみたのですが、コンパイルしてみるとrandom_numberのところの設定がおかしいみたいでうまくコンパイルできません。どこに問題があるのかわからないので困っています。教えて下さい。よろしくお願いします。 module subprogs implicit none contains function vec_cos(a,b) result(vcos) real(8), intent(in) :: a(:), b(:) real(8) ab, vcos if (size(a) /= size(b)) stop ' sr : size(a) /= size(b) ' ab = dot_product(a,a) * dot_product(b,b) if (ab == 0.0d0) then vcos = 0.0d0 else vcos = dot_product(a,b)/sqrt(ab) endif end function vec_cos end module subprogs program main use subprogs implicit none real(8), allocatable :: x(:), y(:) integer n write(*,'(a)', advance = 'no') ' input n : ' read(*,*) n if ( n < 1 .or. n > 100 )stop ' n must be 0 < n < 101 ' allocate(x(n),y(n)) call random_seed call random_number(x,y) write(*,*) 'cos = ', vec_cos(x,y) end program main コンパイル結果 Undefined symbols: "_random_number__", referenced from: _MAIN_ in ccxYbc0C.o ld: symbol(s) not found

  • fortran ニュートン法

    program main real*8 x,xold,y,yold,func,dfunc,dx real*8 eps integer nmax nmax=100 eps=1.0d-9 *initial xold=2.0 do n=1,max yold=xold**2-2 x=xold-yold/xold*2 err=abs(x-xold) if(0.01>err)then write(6,*)x stop'Ended with succes' else y=x**2-2 xold=y end if end do write(6,*)x end を実行すると 4.94065645841246544E-324 という結果になってしまいます。 1.41421356 という解がほしいのに、、 ずっと考えたのですがどこがおかしいかわかりません お願いします、どうすれば正しい解が得られますか?

  • fortran 途中まで考えたのですが。。。。

    エラトステネスのふるい(素数の倍数を除いていって残ったのが素数)で3桁の素数を求めて表示したいです。 私が考えたのは、 1・2~99までの数を素数かどうか調べて、素数を配列に入れていく 2・100~999まで素数の配列の中の数で割って、割り切れたらおしまい。割り切れなかったら表示していく ということです。 しかし下のプログラムではうまく素数配列ができていないようなのです。 ここまでかなり時間がかかったのでこのプログラムに手をいれて これ以外におかしくなるところもどこを直せばいいのか教えてくださるとうれしいです。 C C q223.f C PROGRAM q223 C IMPLICIT NONE C INTEGER N,i,K,s,l REAL a(99),b(99),c(99),X,Y C real M C a(1)=2 a(2)=3 l=2 C DO N=2,99,1 M=N**(0.5) S=M DO i=2,S,1 K=MOD(N,i) IF(K ==0)THEN exit ELSE IF(K /=0)THEN l=l+1 a(l)=N ENDIF ENDDO ENDDO C do N=100,999 do l=1,99 X=a(l) Y=N/X if(Y==0)then exit else if(Y/=0)then write(*,*)N end if end do end do c end よろしくおねがいします

  • FORTRANのプログラム

    今、実験の解析を行っています。 読み込みたいテキストファイルには -1,0.4 0,0,233 -1,0.9 ・・など左側には-1か0のどちらかがあります。 これを -1,0.4 -1,0.9 を含むファイルと 0,0.0233 を含むファイルの二つに分けたいのです。 今プログラムを作っているのですがどうしてもできません。 どうしたらいいのでしょうか? program dat real x(10), y(10) open(7,file='test.txt') do i=1,10 read(7,*,end=200) x(i),y(i) end do do j=1,10 if(x(j).eq.0.0) then open(8,file='aftest1.txt') write(8,*) y(j) else open(9,file='aftest2.txt') write(9,*) y(j) end do close(8) close(9) 200 close(7) end

  • Doループとファンクション(fortran)

    課題で初めてプログラムに取り組んでいるものです。よろしくお願いします。 台形則を使って楕円の面積(の4分の1)を求めるプログラムを作ったのですが、ファンクションで関数を指定するとうまくいきません。 具体的には func(x)=4.0*sqrt(1.0-x**2.0) という関数で、0<=x<=1を1000万分割して面積を近似するという課題です。 本来ならfunc(x)は徐々に減少し、x=1で0になるはずが、実際に走らせてみると、それより手前で0になってあとはNaNがでます。 func(x)以外(x座標の分割の仕方等)はうまく行っており(確認済み)、function形式をやめてメインのプログラムに直接式を書き込んだらうまくいきました。 自分ではなんでこんなことが起こるのか皆目見当が付きません。ご教授お願いしますm(_ _)m

専門家に質問してみよう