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

このQ&Aのポイント
  • 2x2の実行列の固有値を求めるモジュール関数の中で、d > 0 のときに出てくる sign(sqrt(d), -b) の値が示す意味と eval(2) = cmplx(c/e,0.0d0) でなぜ c/eの値が入るのかがわかりません。
  • 質問者は、fortranのプログラムで2x2の実行列の固有値を求めるモジュール関数を作成しています。
  • しかし、d > 0 の場合における sign(sqrt(d), -b) の意味や eval(2) = cmplx(c/e,0.0d0) の c/e の値について理解していません。
回答を見る
  • ベストアンサー

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

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

  • ベストアンサー
  • f272
  • ベストアンサー率46% (8003/17107)
回答No.1

> sign(sqrt(d), -b)の値が示す意味 これは2次方程式の判別式が正のときです。 このとき-b+sqrt(d)と-b-sqrt(d)のどちらも求める解ですが, -b+sqrt(d)と-b-sqrt(d)のどちらが絶対値が大きいかを考えてください。 -bが正なら-b+sqrt(d)の絶対値が大きく,-bが負なら-b-sqrt(d)の絶対値が大きくことが分かるでしょう。 だから絶対値の大きい方を第1の解としています。 > eval(2) = cmplx(c/e,0.0d0) でなぜ c/eの値が入るのか 第2の解は,第1の解eが分かっていれば簡単です。2つの解の積が定数項のcですね。だからc/eが第2の解になります。 なぜこのように解の絶対値によって解の順序を決めているかと言えば,計算精度を高めるためです。 例えば a(1,1:2) = (/1.0d15,1.0d15+1.0d0/) a(2,1:2) = (/1.0d0,1.0d0/) でこのような処理をした場合としない場合を比較してください。

528612
質問者

お礼

なるほど、sign(sqrt(d),-b)の値の示す意味理解できました。絶対値の大きい方を第1解にしてるんですね。 それと、c/eの計算の意味も納得しました。普段あまりそのような解の求め方に馴染みがなかったのでわかってませんでした。ありがとうございました。

関連するQ&A

  • 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

  • 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 実行結果がうまく表示されない

    グローバルモジュールを用いてプログラムを書いたのですが実行結果が表示されません、プログラム中に問題があるのでしょうか?教えて下さい。 module params implicit none integer :: n = 2 end module params module sample implicit none contains subroutine swapvec3(x,y) use params real(8), intent(inout) :: x(n), y(n) real(8) tmp(n) tmp(1:n) = x(1:n) x(1:n) = y(1:n) y(1:n) = tmp(1:n) end subroutine swapvec3 end module sample program main use sample implicit none real(8), allocatable :: a(:), b(:), tmp(:) integer n allocate(a(n),b(n),tmp(n)) call swapvec3(a,b) call random_seed call random_number(a) call random_number(b) call random_number(tmp) write(*,*) ' a = ', a(1:n) write(*,*) ' b = ', b(1:n) write(*,*) ' tmp = ', tmp(1:n) end program main 実行結果  a = b = tmp =

  • fortran グラムシュミットの直行化

    グラムシュミットの直行化を行うプログラムを書いたのですが、実行結果の答えで2列目1行目の答えがマイナスになるはずなのになっていません。自分の計算ではマイナスになったのですが、プログラムに問題があるのでしょうか?教えて下さい。よろしくお願いします。 module subprogs implicit none contains function normal_vec2(v,n) result(nv) integer, intent(in) :: n real(8), intent(in) :: v(n) real(8) nv(n), vl vl = sqrt(dot_product(v,v)) if (vl == 0.0d0) then nv(:) = 0.0d0 else nv(:) = v(:) / vl endif end function normal_vec2 end module subprogs module subprogs2 use subprogs implicit none contains function gs(a,n) result(e) integer, intent(in) :: n real(8), intent(in) :: a(n,n) real(8) e(n,n), dotp integer k, j e(1:n,1) = normal_vec2(a(1:n,1:1),n) do k = 2, n e(1:n,k) = a(1:n,k) do j = 1, k-1 dotp = dot_product(a(1:n,k),e(1:n,j)) e(1:n,k) = e(1:n,k)-dotp*e(1:n,j) enddo e(1:n,k) = normal_vec2(a(1:n,k:k),n) enddo end function gs end module subprogs2 program main use subprogs use subprogs2 implicit none real(8), allocatable :: q(:,:) integer :: n = 2 allocate(q(n,n)) q(1,1:2) = (/2.0d0,1.0d0/) q(2,1:2) = (/1.0d0,2.0d0/) write(*,*) gs(q,n) end program main 実行結果 0.8944271909999159 0.4472135954999579 0.4472135954999579 0.8944271909999159                   ↑                             実計算では-(マイナス)がつく

  • FORTRAN…これってどんなプログラムになりますか??

    DO 10 I=1,47 CALL SUB1 10 CONTINUE STOP END SUBROUTINE SUB1 DIMENSION B1(3),B2(3),C(3),L(3),P(3) CHARACTER*12 A READ(5,50) A,B1,B2 50 FORMAT(A12,3F8.1,3F7.1) X=1.0 DO 11 K=1,300 Y1=(-1.0) Y2=0.0 DO 12 J=1,3 L(J)=(-NINT(B1(J)*10.0/B2(J))) Y1=Y1+X**L(J) Y2=Y2+L(J)*X**(L(J)-1) 12 CONTINUE W=X-Y1/Y2 IF(ABS(W-X).LT.1E-10) GO TO 13 X=W 11 CONTINUE 13 WO=W DO 14 J=1,3 C(J)=WO**L(J) 14 CONTINUE R1=0.0 DO 15 J=1,3 R2=R1+B2(J) R1=R2 15 CONTINUE D=0.0 DO 16 J=1,3 P(J)=B2(J)/R1 D=D+P(J)*ALOG(P(J)/C(J)) 16 CONTINUE E=0.0 DO 17 J=1,3 E=E+(B1(J)/B2(J)*P(J)) 17 CONTINUE WRITE(*,200) A,B2,P,E,D 200 FORMAT(1H,2X,A12,3X,3(F7.1,2X),4X,3(F9.6,X),4X,F9.6,2X,F9.6) RETURN END

  • 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 よろしくおねがいします

  • fortran77教えてください

    fortran77のプログラムについての質問です。 次のプログラムを実行するとどのような結果になるか教えてください REAL A,B,C,D,E,F A=7.0 B=5.0 CALL WASA(A,B,C,D) CALL WASA(C,D,E,F) WRITE(*,*)E,F STOP END SUBROUTINE WASA(P,Q,R,S) REALP,Q,R,S R=P+Q S=P-Q RETURN END

  • 関数のプログラムについて

    任意の二次方程式ax^2+bx+c=0をとくプログラムの作成です 引数をa,b,cとして、解の大きい方を返すというものなのですが、 僕は以下のようにして組んだのですが、うまくいきません。 と、いうより、関数の作り方がいまいちわからないです。 どこが駄目なのか教えてください。 作ってみたやつ↓ #include<math.h> #include<stdio.h> int a,b,c; double d; double x,y,z; int main(void) { a=1; b=2; c=1; printf("ax^2+bx+c=0\n "); d=b^2-4*a*c; if (d<0){printf("kyosuukai\n)} else if(d>=0) { x=(b+sqrt(b^2-4*a*c))/2*a; y=(b-sqrt(b^2-4*a*c))/2*a; if(x>=y){z=x} else if(x<y){z=y} printf("x= %f\n",z); } }

  • fortran エラーについて

    fortranで、副プログラムを使ってデータを昇順または降順に並べ替えるプログラムを入力して実行しようとしたところ、 ・Unexpected junk in formal argument list at (1) ・Two main PROGRAMs at (1) and (2) という2つのエラーが出ました。 これらの改善方法を教えて頂きたいです。 初心者ですので簡単なところで間違えている可能性もありますが、ご指摘いただければ幸いです。 以下、実際に入力したプログラムです。 ------------------------------ implicit none integer::i,n real::x(1000),a(1000),b(1000) n=1000 open(10,file='input-data-1.txt') do i=1,n read(10,*) x(i) end do close(10) open(10,file='output-data-1.txt') do i=1,n call koukan(i,x(i),a(i),b(i)) write(10,'(i4,2f10.3)') i,a(i),b(i) end do close(10) stop end subroutine koukan(i,x(i),shoujun,koujun) implicit none integer::i,n,made real::x(1000),w,shoujun,koujun do made=n-1,1,-1 do i=1,made if(x(i)>x(i+1)) then w=x(i) x(i)=x(i+1) x(i+1)=w end if end do end do shoujun=x(i) do made=n-1,1,-1 do i=1,made if(x(i)<x(i+1)) then w=x(i) x(i)=x(i+1) x(i+1)=w end if end do end do koujun=x(i) return end ------------------------------

  • FORTRAN77のプログラミングについて教えてください。

    ・学校の課題で任意の数値の平均と、入力した数の個数を出力するプログラムを作 りなさいという課題が出たのですがうまくいきません。次にあげるプログラムの 中で修正する部分を教えてください。 *課題2 平均値 integer N real X,T1,M * 初期値 N=0 T1=0 * 累積 10 read(5,*,end=20) X N=N+1 T1=T1+X go to 10 * まとめ 20 if(N.GE.2) then M=T1/N write(6,*) '総数は' ,N, '平均は',M ELSE IF(N.EQ.1) THEN WRITE(6,*) '総数は',N, '平均は',T1 ELSE WRITE(6,*) '数値がない' END IF END IF END ・この問題は最初からよくわかりません。教えてください。  「3つの数a,b,cを読み込む。a,b,cを三角形の3辺の長さとしたとき三角形にな  るかを判定しなさい。三角形にならない場合はその面積をヘロンの公式を求め  て表示する。     s=(a+b+c)/2 , ss=s(s-a)(s-b)(s-c) として       S=sqrt(ss) とする。」 以上の二つです。分かる方お願いします。

専門家に質問してみよう