第1章 UNIX の復習 §1.unix コマンド 1.1. ファイルとディレクトリ ファイル :computer に記憶される情報群(文字情報,数値情報)。 名前が付けられている。 ディレクトリ:ファイルの集合。 名前が付けられている。 file_A file_B file_C :ディレクトリを示す。 :ファイルを示す。 letter ディレクトリletter file_A file_B file_C 図1.1. ディレクトリの概念図 図1.2. 図1.1と等価なツリー構造 ○unix の階層型ファイル構造 ルート・ディレクトリ / users f g tmp etc lib bin h システム管理 Library 実行可能な 者が生成する ルーチン オブジェク ファイル トファイル ae94501 dev ae94502 … 周辺装置 に対応す るファイ ル te007 ユーザがログインしたときに最初に入るディレクトリ。 ホ ー ム ・ デ ィ レ ク ト リ と呼ばれる。 図1.3. 階層型ファイル構造の一例. -1- 1.2. ファイル操作とディレクトリ操作 以下の例では下線部を施した部分はユーザが入力した部分であり,それ以外の部分は WS の出力を示します。 1)ディレクトリ操作 ○ディレクトリの作成 [例1] (ae97001@dipfr:4) mkdir report mkdir ディレクトリ名 確認するには (ae97001@dipfr:5) ls ./ .cshrc ../ .exrc (ae97001@dipfr:6) .login .profile .pvtejrc .pvtjerc .rhosts .twmrc SDIC TDIC report/ test [例2] (ae97001@dipfr:6) mkdir paper letter 確認するには (ae97001@dipfr:7) ls ./ .exrc ../ .login .cshrc .profile (ae97001@dipfr:8) .pvtejrc .pvtjerc .rhosts ○ディレクトリの削除 [例3] (ae97001@dipfr:8) rmdir report .twmrc SDIC TDIC letter/ paper/ report/ test rmdir ディレクトリ名 確認するには (ae97001@dipfr:9) ls ./ .exrc ../ .login .cshrc .profile (ae97001@dipfr:10) .pvtejrc .pvtjerc .rhosts .twmrc SDIC TDIC letter/ paper/ test ○ワーキング・ディレクトリ(現在自分がいるディレクトリ)の移動 cd 移動先のディレクトリ名 [例4] (ae97001@dipfr:10) cd letter /users/f2/ae97001/letter ←ワーキング・ディレクトリが表示される。 ○ワーキング・ディレクトリの表示 [例5] (ae97001@dipfr:11) pwd pwd -2- /users/f2/ae97001/letter ○ホームディレクトリへの移動 [例6] (ae97001@dipfr:12) cd /users/f2/ae97001 (ae97001@dipfr:13) cd [練習2] WS に接続後,上記[例1]∼[例6]を実行してみなさい。 2) ファイル操作 先ず,準備として以下の操作をして下さい。 [総合情報処理センターの場合] (ae97001@dipfr:13) cd letter (ae97001@dipfr:14) cp /disk2/e/te007/edu/skel/letter . [情報棟 1F 計算機室の場合] eieis 13: cd letter eieis 14: cp /home/is6/te007/skel/letter . ○ファイルの複写 cp 複写したいファイル名 新ファイル名 [例7] (ae97001@dipfr:15) cp letter letter2 確認するには (ae97001@dipfr:16) ls ./ ../ letter (ae97001@dipfr:17) letter2 ○ファイルの移動(その1) mv 移動したいファイル名 新ファイル名 [例8] (ae97001@dipfr:17) mv letter2 letter1 確認するには (ae97001@dipfr:18) ls ./ ../ letter (ae97001@dipfr:19) letter1 ○ファイルの削除 rm ファイル名 [例9] (ae97001@dipfr:19) rm letter1 rm: file1 を消去しますか (y/n)? y (ae97001@dipfr:20) 確認するには (ae97001@dipfr:20) ls -3- ./ ../ letter (ae97001@dipfr:21) ○ファイルの移動(その2) mv ファイル名 移動するディレクトリ名 [例10] (ae97001@dipfr:21) mv letter /users/f2/ae97001/paper または (ae97001@dipfr:21) mv letter ../paper 確認するには (ae97001@dipfr:22) cd /users/f2/ae97001 (ae97001@dipfr:23) cd paper /users/f2/ae97001/paper (ae97001@dipfr:24) ls ./ ../ letter (ae97001@dipfr:25) 注1)『.』 :ワーキング・ディレクトリを示します。 『..』 :ワーキング・ディレクトリの1つ上のディレクトリを示す。 『~』 :ホームディレクトリを示す。 cat ファイル名 ○ファイルの内容表示 [例11] (ae97001@dipfr:25) cat letter Welcome to Yonezawa Campus! Let's have a good time with us, shall we? Hereafter, We would like to show how to use a engineering work station that works on UNIX environment. Follow us and study hard, and you will be a professional user of EWS. (ae97001@dipfr:26) [練習3] 上記[例7]∼[例11]を実行してみなさい。 1.3. パスワードの変更 passwd [例12] (ae97001@dipfr:26)passwd passwd: Changing password for ae97001 ←現在のパスワードを入力する。表示されない。 Old password: New password: ←新パスワードを入力する。表示されない。 Re-enter new password: ←新パスワードを再入力する。表示されない。 (ae97001@dipfr:27)cd (ae97001@dipfr:28) パスワードを変更する際には,他人に見られないようにするため(つまりセキュリティ上 の理由から),入力した文字が画面に表示されませんので,ミスの無いように入力して下 -4- さい。 [練習4] 上記[例12]を参考にしてパスワードを変更しなさい。 1.3. リダイレクションとパイプライン unix では入力データを標準入力から受け取り,処理結果を標準出力に出力します。通 常,標準入力はキーボードに,標準出力はディスプレイに割り当てられています。この標 準的な入出力をファイルに変更することをリダイレクションと呼びます。 入力の変更は『<』で,出力の変更は『>』で(既に存在しているファイルを指定し た場合には,ファイルの元の内容が消えます)指定します。また,既に存在するファイル の内容にコマンドの出力結果を追加するには『>>』で指定します。以下にリダイレクシ ョンの例を示します。 [例13] ファイル名の一覧を file1 に出力する。 (ae97001@dipfr:28) ls > file1 確認するには (ae97001@dipfr:29) cat file1 ./ ../ .cshrc .exrc .login .profile .pvtejrc .pvtjerc .rhosts .twmrc SDIC TDIC file1 letter/ paper/ test (ae97001@dipfr:30) [例14] 現在の日付と時刻をを file2 に出力する。 (ae97001@dipfr:30) date > file2 ←『date』は日付と時刻を表示するコマンドです。 確認するには (ae97001@dipfr:31) cat file2 1999年04月16日 (日) 22時09分54秒 JST (ae97001@dipfr:32) [例15] file2 の内容を file1 に追加する。 (ae97001@dipfr:32) cat file2 >> file1 確認するには -5- (ae97001@dipfr:33) cat file1 ./ ../ .cshrc .exrc .login .profile .pvtejrc .pvtjerc .rhosts .twmrc SDIC TDIC file1 letter/ paper/ test 1999年04月16日 (日) 22時09分54秒 JST (ae97001@dipfr:34) [練習5] 上記[例13]∼[例15]を実行しなさい。 パイプラインはコマンドを記号『|』で繋ぐことにより前のコマンドの標準出力を次 のコマンドの標準入力にするものです。 [例16] file1 の行数を表示する。 (ae97001@dipfr:35) cat file1|wc -l 17 (ae97001@dipfr:36) この例では cat file1 の標準出力即ち file1 の内容表示の結果を標準入力として wc -l を 実行しています。一般に,『wc -l ファイル名』はそのファイルの行数を表示するコマン ドですから,上の例では file1 の行数を表示することになります。 -6- 1.4. unix の基本的コマンド コマンド 機能の概略 ワーキング・ディレクトリの表示。 pwd ワーキング・ディレクトリを d1 に変える。 cd d1 ホーム・ディレクトリへ戻る。 cd cp f1 f2 ファイル f1 を f2 にコピーする。 date 現在の日付と時刻を表示。 rm f1 ファイル f1 を削除。 システムの使用者を表示。 who ls -la ワーキング・ディレクトリの全ファイル名と属性の表示。 ls -a ワーキング・ディレクトリの全ファイル名を表示。 diff f1 f2 2つのファイル f1 と f2 の内容の比較照合。 mkdir d1 新ディレクトリ d1 の作成。 rmdir d1 空きディレクトリ d1 の削除。 rm -r d1 ディレクトリ d1 の削除(d1 の配下にある全ファイルも一緒に)。 mv f1 f2 ファイル名を f1 から f2 に変更。 mv d1 d2 ディレクトリ名を d1 から d2 に変更。 cat f1 ファイル f1 の内容の表示。 more f1 ファイル f1 の内容を1画面ごとに表示。 man コマンド名 lpr f1 オンラインマニュアルの表示。 ファイル f1 をプリンタに出力。 lpq プリンタの待ち行列を表示。 mule テキストエディタ Mule の起動。 注1)f1 や f2 はファイル名を,d1 や d2 はディレクトリ名を表します。 -7- §2. テキストエディタ Mule テキストエディタ とはプログラム,電子メイルの内容などのテキストファイルを作 成する際に使用するツールのことを指します。テキストエディタ Mule は非常に多くの機 能を備えているほか,その拡張性の高さから,unix 標準のツールではないにもかかわらず, 実質的にunix のエディタとして多くのユーザからの支持を得ています。ここでは,Mule の起動と終了方法,それに日本語 tutorial (日本語で Mule の解説が書いてある)を見る方 法について解説します。 2.1. Mule の起動方法 Mule だけの起動 Mule を用いたファイルの作成や修正 mule mule ファイル名 [例1] (ae97001@dipfr:35) mule とすると図2.1のような初期画面が表示されます。 GNU Emacs 19.28.2 (sparc-sun-solaris2.3, X toolkit) Copyright (C) 1994 Free Software Foundation, Inc. of Mon7 Jan 2on 1997 dipfe Type C-h for help; C-x u to undo changes. (`C-' means ey.) use CTRL k To kill the Emacs job, type C-x C-c. Type C-h t for a tutorial on using Emacs. Type C-h i to enter Info, which you can use to read ation. GNU document GNU Emacs comes with ABSOLUTELY NO WARRANTY; You may give out copies of Emacs; type C-h Type C-h C-d for information on getting the type C-h C-w ll details. for fu C-c to seeions. the condit latest version. Mule Version 2.3 (SUETSUMUHANA) of 1995.7.24 Type C-h T for a Japanese/Korean/Thai tutorial on For any other Mule specific information, Type C-h [--]E_:-----Mule: *scratch* For information about the GNU 12:42am Project and using Mule. i andenuselect `mule'. m (Lisp Interaction)--L16--All -----its goals, type p. C-h C- 図2.1. Mule の初期画面。但し,総合情報処理センターのWS の場合。 -8- 2.2. Mule の終了方法 終了方法 C-x C-c 注)C-x はコントロールキー(CTRLキー)を押しながら,『x』キーを押すことを意味する。 [練習6] Mule を起動した後,終了しなさい。 2.3. 日本語 tutorial Mule には tutoral (手引き書)があります。図2.1をよく見ると下の方に Type C-h T for a Japanese/Korean/Thai tutorial on using Mule. と書いてあるのが見えるでしょう。即ち,C-h T とタイプすると(CTRLキーを押しながら, 『h』キーを押した後,シフトキーを押しながら『T』キーを押すと), Language: という表示が画面の下側に現れます。これは tutorial を何語で表示するかを質問してきて いるのを示します。そこで,『Japanese』とタイプすると,図2.2のような日本語の手引き 書を読むことが出来ます。この手引き書に従ってMule の操作方法を習得することが出来 ます。 [練習7] Mule の tutorial を開き,操作方法を習得しなさい。2回ぐらいしないと習熟でき ないでしょう。 ============================== 日本語 GNUEMACS(Mule) 入門編 ============================== 注意: この入門編は、「習うより慣れろ」をモットーに作成されていま す。">>" から始まる行は、その時何をすべきかを指示しています。 Mule のコマンドを入力するときには、一般的にコントロール・キー(キー・ トップに、CTRL あるいは、CTL と書いてある)やメタ・キー(普通、エスケープ・ キーを使う)が使われます。そこで、CONTROL とか META とか書く代わりに、次の ような記号を使うことにします。 C-<文字> コントロール・キーを押したまま、<文字>キーを押します。例えば、 C-f は、コントロール・キーを押しながら f のキーを押すことを 意味します。 >> それでは、C-v(View Next Screen; 次の画面を見る)をタイプして みて下さい。次の画面に進むことができます。 以降、一画面を読み終えるたびに同様にして次の画面に読み進んで 下さい。 [--]J.EE:-----Mule: TUTORIAL.jp (Fundamental)--L1--Top----------------- 図2.2. Mule の tutorial の画面。 -9- 第2章 Fortran 90 入門 §1 計算 1.0 実数の四則演算 例 題 2つのデータ a,b を読み込み,和 s, 差 d, 積 p, 商 q を求め,これらを印字する. 文 法 行,文,文番号,コメント文,継続行,変数,算術代入文,算術式,stop文, end文,read文,書式付き write文,format文,x形編集記述子,アポストロフィ編集 記述子,斜線編集記述子 [プログラム] *------------------------------------------------------------------* ex100.f in sec1 * * operations on real numbers * * programmed by A.Kamitani * updated at 1993 04/25 *------------------------------------------------------------------write(*,100) 100 format(' Input values of a and b! ') read (*, * ) a,b write(*,200) a,b 200 format(//'a=',e12.5,5x,'b=',e12.5) s=a+b d=a-b p=a*b q=a/b write(*,300) s,d,p,q 300 format(/'s=',e12.5,5x,'d=',e12.5/ & 'p=',e12.5,5x,'q=',e12.5) stop end [実行結果] [dipfr:te007|46]frt ex100.f 情報棟1Fの計算機室では,f77 ex100.f [dipfr:te007|47]a.out Input values of a and b! 1.0,3.0 a= 0.10000e+01 b= 0.30000e+01 s= 0.40000e+01 p= 0.30000e+01 [dipfr:te007|48] d=-0.20000e+01 q= 0.33333e+00 - 10 - 1.1 整数計算 例 題 2つの整数データ m, n を読み込み,和,差,積,商等を計算する.次に,実数 データ a, b を読み込み,a3, b3 を計算する. 文 法 整数型,実数型,暗黙の型宣言,算術演算子 **,式の評価順序,整数の編集 [プログラム] *-------------------------------------------------------------------* ex110.f in sec1 * * operations on integers and powers of real numbers * * programmed by A.Kamitani * updated at 1993 04/25 *-------------------------------------------------------------------100 format(' Input values of m,n,a and b! ' ) 200 format(//'m=',i5,5x,'n=',i5/'a=',e12.5,5x,'b=',e12.5) 300 format(///'m+n=',i5,5x,'m-n=',i5/ & 'm*n=',i5,5x,'m/n=',i5/ & 'm+n*m**2=',i5 ) 400 format(///'a**2=',e12.5/'b**3=',e12.5 ) * *----- Input parameters from keyboad. * write(*,100) read (*, * ) m,n,a,b * *----- echo-back input data. * write(*,200) m,n,a,b * *----- calculations. * is=m+n id=m-n ip=m*n iq=m/n i =m+n*m**2 pa=a**2 pb=b**3 * *----- output calculated results. * write(*,300) is,id,ip,iq,i write(*,400) pa,pb stop end - 11 - [実行結果] [dipfr:te007|49]frt ex110.f 情報棟1Fの計算機室では,f77 ex110.f [dipfr:te007|50]a.out Input values of m,n,a and b! 10,3,0.1,-0.2 m= 10 n= a= 0.10000e+00 3 b=-0.20000e+00 m+n= 13 m-n= m*n= 30 m/n= m+n*m**2= 310 7 3 a**2= 0.10000e-01 b**3=-0.80000e-02 [dipfr:te007|51] [ 演習問題 ( 第1回 ) ] [ 例題1 ] §1にある2つの例題プログラムを打ち込んで実行し,実行結果がテキストと同じに なるか確かめなさい. [ 演習1 - 1 ] 円の半径 R を読み込んで,その円周の長さと面積を計算するプログラムを作成しな さい. [ 演習1 - 2 ] 三角形の3つの頂点の座標 (x 1, y 1), (x 2, y 2), (x 3, y 3) を読み込んで,面積を求めるプ ログラムを作成しなさい. 三角形の面積 S は, で計算できる. 絶対値を求めるには,組み込み関数 絶対値を求めて,その値を変数 abs を用いればよい.例えば,変数 kyon2 の x に格納したいなら, x = abs(kyon2) とすればよい. - 12 - §2 判定と飛び越し 例 題 整数データ I 1, I 2, I 3, …, I n を読み込み,これらを印字し,かつ,その内の最小 値とデータの数 n を印字する.ここでデータは5桁以内の正整数であり,データ の尽きた印としては 0 または負の整数を入力するものとする. 文 法 実行文,非実行文,単純 go to 文,論理 if 文,算術関係式,関係演算子, continue 文,組み込み関数 [プログラム] *-------------------------------------------------------------------* ex200.f in sec2 * * minimum of a set of integers * * programmed by A.Kamitani * updated at 1993 04/27 *-------------------------------------------------------------------100 format(//' Searching Minimum Values of Integers ' & /' Input Data ! ') 200 format(i10 ) 300 format(//' minimum value =',i6,5x & /' number of data=',i3 ) * write(*,100) * *----- setting initial value. * min = 100000 n =0 10 continue read (*,*) ivalue * *----- decision of whether datum is input or not. * if(ivalue.le.0) go to 20 * write(*,200) ivalue * if(ivalue.lt.min) min=ivalue n = n+1 go to 10 20 continue * *----- output minimum and number of data. * write(*,300) min,n stop end - 13 - [実行結果] [dipfr:te007|57]frt ex200.f [dipfr:te007|58]a.out Searching Minimum Values of Integers Input Data ! 123 123 456 456 789 789 12 12 345 345 0 minimum value = 12 number of data= 5 [dipfr:te007|59] [組み込み関数] exp(x) log(x) log10(x) sqrt(x) abs(x) float(n) 指数関数 ex 自然対数 logex 常用対数 log1 0x 平方根 絶対値 |x| 整数 n の 実数化 max(x1,x2,…,xn) sin(x) 正弦関数 sin x asin(x) 逆正弦関数 sin-1x cos(x) 余弦関数 cos x acos(x) 逆余弦関数 cos-1x tan(x) 正接関数 tan x atan(x) 逆正接関数 tan-1x sinh(x) 双曲線正弦関数 sinh x mod(m,n) 整数 m を整数 n で割った剰余 cosh(x) tanh(x) x1, x2, …, xn の最大値 双曲線余弦関数 cosh x 双曲線正接関数 tanh x int(x) nint(x) min(x1,x2,…,xn) 切り捨てによる 整数化 四捨五入による 整数化 x1, x2, …, xn の最小値 [関係演算子] .lt. .gt. .eq. less than < greater than > equal to = .le. .ge. .ne. - 14 - less than or equal to ≦ greater than or equal to ≧ not equal to ≠ 2.1 べき級数 解 説 x の関数 f(x) が,x のべき級数として, (1) の形に表されるものとする.このとき,一般項を (2) と表すと,t n/t n-1 は x と n の簡単な式になることが多い.このような場合はその関係を用 いて t n-1 の値から t n を計算するのがよい.また,第 n 項までの部分和を sn で表すと, が成り立つことはいうまでもない. (3) 例 題 指数関数 e x は,べき級数 (4) で表される.このとき,t n = x n/n! と置くと, t n = t n-1・x/n (5) という漸化式が成り立つ.これを用いて,与えられた x の値に対して,e x を計算する. あらかじめ読み込んでおいた小さい値 e に対して |t n / sn|< e (6) となったところで打ち切り,そのときの sn の値を求める関数値とみなす. 尚,たとえ e の与え方が不適当であっても,n は高々 100 までで止まるようにする. 文 法 算術代入文(変数の値の変更) [プログラム] *-------------------------------------------------------------------* ex210.f in sec2 * * Taylor Series for Exp(x) * * programmed by A.Kamitani * updated at 1993 05/08 *-------------------------------------------------------------------100 format(' Input value of eps ! ' ) 200 format(' Input value of x ! ' ) 300 format(/'x=',e13.6/' n',9x,'t',15x,'s' ) 400 format(i3,2(2x,e13.6) ) 500 format(/'Exp(',e13.6,')=',e13.6,5x,'n=',i2/) 600 format( 'Internal Function :',e13.6 ) * nmax = 100 * *----- input parameters from keyboard. * write(*,100) read (*, * ) eps write(*,200) - 15 - read (*, * ) x write(*,300) x * *----- summation of series. * n = 0 t = 1.0 s = 1.0 10 continue n = n+1 t = t*x/float(n) s = s+t write(*,400) n,t,s c c----- convergence judgement. c if(abs(t/s).lt.eps) go to 20 if(n.lt.nmax) go to 10 20 continue * *----- output calculated results. * write(*,500) x,s,n c c----- comparison of results with value of internal function. c sfunc = exp(x) write(*,600) sfunc * stop end [実行結果] [dipfr:te007|62]frt ex210.f [dipfr:te007|63]a.out Input value of eps ! 1.0e-5 Input value of x ! 2.0 x= 0.200000e+01 n t 1 0.200000e+01 2 0.200000e+01 3 0.133333e+01 4 0.666667e+00 5 0.266667e+00 6 0.888889e-01 7 0.253968e-01 8 0.634921e-02 9 0.141093e-02 10 0.282187e-03 11 0.513067e-04 s 0.300000e+01 0.500000e+01 0.633333e+01 0.700000e+01 0.726667e+01 0.735556e+01 0.738095e+01 0.738730e+01 0.738871e+01 0.738900e+01 0.738905e+01 Exp( 0.200000e+01)= 0.738905e+01 n=11 Internal Function : 0.738906e+01 [dipfr:te007|64] - 16 - [ 演習問題 ( 第2回 ) ] [ 例題2 ] §2の2つの例題プログラムを打ち込んで実行し,実行結果がテキストと同じになる か確かめなさい. [ 演習2 - 1 ] n 個の実数データx 1, x 2, …, x n がある.データの個数 n を最初に読み込んだ後,デー タを逐次読み込んで,それらのデータの最大値と最小値を求めるプログラムを作成しなさ い. テキストの例題のように if 文を用いてもよいが,組み込み関数 max, min を用いると, 便利である.例えば,変数 a1, a2 の内小さいほうの値を変数 asmall に,大きいほうを 変数 alarge に格納したいときは, alarge = max(a1,a2) asmall = min(a1,a2) とすればよい. 1個目のデータだけ特別扱いするのがキーポイントです. [ 演習2 - 2 ] | x | < 1 の時,関数 log(1+x) はべき級数 で表される.このべき級数を用いて,与えられた x の値に対して,log(1+x) の値を計算す るプログラムを作成しなさい.但し,| x | ≥ 1を満たす x が入力されたときには, The absolute value of x must be less than 1.0. というメッセージを出力した後,もう一度 x の値を入力するようにプログラムを作成しな さい. - 17 - §3 配列と繰り返し 3.0 積の和 例 題 整数 n の値とデータa1, a2, …, an および b1, b2, …, bn をこの順に入力し,それ から a1 と b1 を1行に,a2 と b2 を次の1行に,…というふうに印字し,かつ積 の和 を計算して印字する. 文 法 配列,配列宣言子,型宣言文,添字式,配列要素,do 文,端末文,do ループの 範囲,do 形並び,do 形仕様 [プログラム] *----------------------------------------------------------------------* ex300.f in sec3 * * summation of products * * programmed by A.Kamitani * updated at 1993 05/01 * version 1.1 at 1998 10/07 *----------------------------------------------------------------------dimension adim(20),bdim(20) 100 format(/'Input number of data ! ') 200 format(/'Input values of adim(1),adim(2),...,adim(n)!') 300 format(/'Input values of bdim(1),bdim(2),...,bdim(n)!') 400 format(//' Summation of Products '//8x,'a',14x,'b'/) 500 format(2(2x,e13.6)) 600 format(/10x,'s=',e13.6) * *----- input parameters. * write(*,100) read (*, * ) n write(*,200) read (*, * ) (adim(i),i=1,n) write(*,300) read (*, * ) (bdim(i),i=1,n) * *----- echo-back input data. * write(*,400) write(*,500) (adim(i),bdim(i),i=1,n) * *----- calculation of inner products. * s = 0.0 do i=1,n s = s+adim(i)*bdim(i) end do * *----- output calculated results. * write(*,600) s - 18 - * stop end [実行結果] [dipfr:te007|7]frt ex300.f [dipfr:te007|8]a.out Input number of data ! 4 Input values of adim(1),adim(2),...,adim(n)! 1.0,2.0,3.0,4.0 Input values of bdim(1),bdim(2),...,bdim(n)! -1.0,-2.0,-3.0,-4.0 Summation of Products a b 0.100000e+01 0.200000e+01 0.300000e+01 0.400000e+01 -0.100000e+01 -0.200000e+01 -0.300000e+01 -0.400000e+01 s=-0.300000e+02 [dipfr:te007|9] 3.1 多項式の計算 解 説 n 次の多項式 (1) の値を求める方法としては,Horner の方法が標準的である. (2) (3) 上記漸化式を用いて得られる pn の値が p(x) の値に等しいのである. 例 題 多項式 (1) の次数 n と係数 a0, a1, …, an をまず読み込んでおく.次に, x の値 の下限 x min,上限 x max,およびその区間を分割する数 m を読み込み,(m+1) 個 の点: (4) に対して多項式の値 p(x k ) を計算する. 文 法 配列の寸法の下限 - 19 - [プログラム] *----------------------------------------------------------------------* ex310.f in sec3 * * evaluation of polynomial by using Horner's method * * programmed by A.Kamitani * updated at 1993 05/01 * version 1.1 at 1998 10/07 *----------------------------------------------------------------------dimension adim(0:20) * 100 format(/'多項式の次数を入力しなさい!') 200 format(/'係数の値を入力しなさい!') 300 format(/'x の区間の下限,上限,分割数を入力しなさい!') 400 format(i5,5x,'x=',e13.6,5x,'p=',e13.6) * *----- input parameters. * write(*,100) read (*, * ) n write(*,200) read (*, * ) (adim(j),j=0,n) write(*,300) read (*, * ) xmin,xmax,ndiv * *----- calculation of polynomial. * h = (xmax-xmin)/float(ndiv) do k=0,ndiv x = xmin+h*float(k) p = adim(0) do j=1,n p = p*x+adim(j) end do write(*,400) k,x,p end do * stop end [実行結果] [dipfr:te007|20]frt ex310.f [dipfr:te007|21]a.out 多項式の次数を入力しなさい! 5 係数の値を入力しなさい! -252.0,630.0,-560.0,210.0,-30.0,1.0 x の区間の下限,上限,分割数を入力しなさい! 0.2,0.5,3 0 x= 0.200000e+00 p=-0.152640e+00 1 x= 0.300000e+00 p= 0.270640e+00 2 x= 0.400000e+00 p= 0.307519e+00 3 x= 0.500000e+00 p= 0.000000e+00 [dipfr:te007|22] - 20 - [ 演習問題 ( 第3回 ) ] [ 例題3 ] §3の2つの例題プログラムを打ち込んで実行し,実行結果がテキストと同じになる か確かめなさい. [ 演習3 - 1 ] n 個のデータ x 1, x 2, …, x n がある.データの個数 n とデータを逐次読み込んで,それ らのデータの最大値と最小値を求めるプログラムを作成しなさい.但し,データは配列と して入力するものとし,最大値と最小値を計算する際には,必ず do 文を用いなさい. [ 演習3 - 2 ] n 個のデータ x 1, x 2, …, x n を配列に読み込んで,データの平均値と標準偏差を求める プログラムを作成しなさい.但し,平均値と標準偏差は でそれぞれ定義される. [ 演習3 - 3 ] l×m 行列 A とm×n 行列 B の行列要素を配列に読み込んで,行列の積 C = A×B の行 列要素を計算するプログラムを作成しなさい.但し,入力する変数及び配列は l, m, n と 行列 A, B の配列要素である. 変数名や配列名は必ず3文字以上を使用してください. ex.) l →lsize A → adim m →msize B → bdim n →nsize C → cdim - 21 - §4 block if 文 例 題 n 人の学生の身長データ s1, s2, …, sn と体重データ t 1, t 2, …, t n を読み込んで, 大相撲の新弟子検査に合格する学生の人数を求めるプログラムを作成する.また, 体重だけ合格基準に達しない学生の数,身長だけ基準に達しない学生の数,体重 も身長も基準に達しない学生の数も出力する.但し,合格基準を身長が 175cm 以上,体重が 80kg 以上とする. 192 169 175 152 201 182 身長 体重 55 92 86 98 105 文 法 編集記述子の反復,論理演算子,block if 文 パターン1 ] [パ if(e) then (*1) end if 論理式 e が真→(*1) を実行した後, end if 文の次を実行 論理式 e が偽→ end if 文の次を実行 パターン2 ] [パ if(e) then (*1) 論理式 e が真→(*1) を実行した後, end if 文の次を実行 (*2) 論理式 e が偽→(*2) を実行した後, end if 文の次を実行 else end if パターン3 ] [パ if(e1) then (*1) else if(e2) then (*2) end if 論理式 e1 が真→(*1) を実行した後, end if 文の次を実行 論理式 e1 が偽→(*2) を実行した後, 論理式 e2 が真 end if 文の次を実行 それ以外 → end if 文の次を実行 パターン4 ] [パ if(e1) then (*1) else if(e2) then (*2) 論理式 e1 が真→(*1) を実行した後, end if 文の次を実行 論理式 e1 が偽→(*2) を実行した後, 論理式 e2 が真 end if 文の次を実行 else (*3) それ以外 → (*3) を実行した後, end if 文の次を実行 end if - 22 - 72 [論理演算子] 論理演算子 .not. .and. .or. 機 能 例 .not.b1 b1 が真なら偽,偽なら真 論理積 b1.and.b2 b1, b2 が共に真のときのみ真,他の場合は偽 論理和 b1.or.b2 b1, b2 が共に偽のときのみ偽,他の場合は真 但し,b1, b2 は論理式である. 否定 [プログラム] *----------------------------------------------------------------------* ex500.f in sec4 * * 大相撲の新弟子検査 * * programmed by A.Kamitani * updated at 1993 05/02 * version 1.1 at 1998 10/07 *----------------------------------------------------------------------dimension shi(10),tai(10) * 100 format('新弟子希望者は何人ですか?'/ & '但し,10人以下にしてください。') 200 format('ちゃんと入れて下さい。') 300 format('エントリーNo.',i3,'番の身長と体重は?' ) 400 format(/'合格最低ラインの身長と体重を入力しなさい!') 500 format(//13('*'),'結果発表',13('*')) 600 format('合格者は ',i3,' 人') 700 format('身長だけが足りなかった人は ',i3,' 人') 800 format('体重だけが足りなかった人は ',i3,' 人') 900 format('身長も体重も足りなかった人は',i3,' 人') * *----- データの入力 * write(*,100) 10 read (*, * ) ndeshi c c----- parameter check against out-of-range error. c if(ndeshi.le.0 .or. ndeshi.gt.10) then write(*,200) go to 10 end if c do k=1,ndeshi write(*,300) k read (*, * ) shi(k),tai(k) end do c write(*,400) read (*,*) gsh,gtai * *----- 新弟子検査 * igoka=0 isshi=0 istai=0 ismon=0 - 23 - * do k=1,ndeshi if(shi(k).ge.gsh.and.tai(k).ge.gtai) then igoka=igoka+1 else if(shi(k).lt.gsh.and.tai(k).ge.gtai) then isshi=isshi+1 else if(shi(k).ge.gsh.and.tai(k).lt.gtai) then istai=istai+1 else ismon=ismon+1 end if end do * *----- 結果の表示 * write(*,500) write(*,600) write(*,700) write(*,800) write(*,900) stop end igoka isshi istai ismon [実行結果] [dipfr:te007|31]frt ex400.f [dipfr:te007|32]a.out 新弟子希望者は何人ですか? 但し,10人以下にしてください。 6 エントリーNo. 1番の身長と体重は? 192.0,55.0 エントリーNo. 2番の身長と体重は? 169.0,92.0 エントリーNo. 3番の身長と体重は? 175.0,86.0 エントリーNo. 4番の身長と体重は? 152.0,98.0 エントリーNo. 5番の身長と体重は? 201.0,105.0 エントリーNo. 6番の身長と体重は? 182.0,72.0 合格最低ラインの身長と体重を入力しなさい! 175.0,80.0 *************結果発表************* 合格者は 2 人 身長だけが足りなかった人は 2 人 体重だけが足りなかった人は 2 人 身長も体重も足りなかった人は 0 人 [dipfr:te007|33] - 24 - [ 演習問題 ( 第4回 ) ] [ 例題4 ] §4の例題プログラムを打ち込んで実行しなさい. [ 演習問題4 - 1 ] 漸化式: を満たす数列 がある.初項 a1 の値を読み込んで,極限値 を計算するプログラムを作成しなさい. 数列が収束したかどうかは,条件: を判定しなさい.但し,e の値はキーボードから入力するようにしなさい. 第 nmax 項まで求めて収束しないときには, The series does not converge! と出力するようにしなさい. 数列 さい. の各項を求める問題ではないので,プログラム中では配列を用いないで下 [ 演習問題4 - 2 ] n 組の実数データ (x 1, y 1), (x 2, y 2), (x 3, y 3), …, (x n, y n) と x, y を読み込んで, を満足するデータの数をそれぞれ求めるプログラムを作成しなさい. - 25 - §5 サブルーチン副プログラム -1 5.0 読み込み,計算,印刷 例 題 §1の例題を次の3つの手続きを用いて実現する. 読み込み:2つのデータ a, b を読み込み,印字する. 計 算 :a と b とから,和 s,差 d,積 p,商 qを求める. 印 刷 :計算結果 s, d, p, q を印字する. これら3つの手続きをそれぞれサブルーチンにして,1つの主プログラムでこれ を使う形にプログラムする. 文 法 サブルーチン副プログラム,subroutine 文,主プログラム,program 文,call 文, return 文,common 文,無名共通ブロック,名前付き共通ブロック,手続き,プ ログラム単位,p 形編集記述子 注 意 common 文の中の変数名は,プログラム単位によって違っていても,それが並ん でいる順に同じ場所を指す.しかし,格別の理由がないかぎり,全てのプログラ ム単位で同じ名前を使うほうが,混乱の恐れが少ない. [プログラム] *-------------------------------------------------------------------* ex500.f in sec5 * * サブルーチンを用いたプログラム(実数の演算) * * programmed by A.Kamitani * updated at 1993 05/07 *-------------------------------------------------------------------program ex500 call input call calcu call outpt stop end * subroutine input common/coinp/a,b 100 format(/'a と b の値を入力しなさい.' ) 200 format(/' a=',1pe12.5,5x,' b=',1pe12.5) write(*,100) read (*, * ) a,b write(*,200) a,b return end * subroutine calcu common/coinp/a,b common/coout/s,d,p,q s=a+b d=a-b p=a*b q=a/b return end * - 26 - subroutine outpt common/coout/s,d,p,q 100 format(/'和=',1pe12.5,5x,'差=',1pe12.5 & /'積=',1pe12.5,5x,'商=',1pe12.5) write(*,100) s,d,p,q return end [実行結果] [dipfr:te007|88]frt ex500.f [dipfr:te007|89]a.out a と b の値を入力しなさい. 1.0,3.0 a= 1.00000e+00 和= 4.00000e+00 積= 3.00000e+00 b= 3.00000e+00 差=-2.00000e+00 商= 3.33333e-01 [dipfr:te007|90] 5.1 整 列 例 題 与えられた n 組の正整数 (a1, x 1), (a2, x 2), …, (an, x n) を,x i の値の大きいほう から順に並べ替える.整列には,n と配列内のデータ (a1, a2, …, an), (x 1, x 2, …, x n) とを受け取り,同じ配列に並べ替えた結果を返すサブルーチンを用いる. 文 法 common 文を用いた配列宣言,書式制御の戻り,stop 文に続く文字列 [プログラム] *----------------------------------------------------------------------* ex510.f in sec5 * * n 組の正整数を Xi の値の大きいほうから整列する * * programmed by A.Kamitani * updated at 1993 05/08 * version 1.1 at 1998 10/08 *----------------------------------------------------------------------*======================================================================= 主プログラム * *======================================================================= program ex510 call input call sort0 call outpt stop end *======================================================================= 入力用サブルーチン * *======================================================================= subroutine input - 27 - common/codata/ia(100),ix(100) common/conumb/ndata 100 format(/'データ数を入力しなさい。') 200 format(/'Parameter Error in input' & /'ndata > 100',3x,'ndata =',i5/) 300 format(/'ia(1),ix(1),ia(2),ix(2),… を入力しなさい。') * write(*,100) read (*, * ) ndata c c----- データのチェック。 c if(ndata.gt.100) then write(*,200) ndata stop ' *** 異常終了 in input *** ' end if * write(*,300) read (*, * ) (ia(n),ix(n),n=1,ndata) * return end *======================================================================= 出力用サブルーチン * *======================================================================= subroutine outpt common/codata/ia(100),ix(100) common/conumb/ndata 100 format(/' 整列後のデータ ') 200 format(i6,2x,i6) * write(*,100) write(*,200) (ia(n),ix(n),n=1,ndata) return end *======================================================================= 整列用サブルーチン * *======================================================================= subroutine sort0 common/codata/ia(100),ix(100) common/conumb/ndata * do i=1,ndata c c----- ix(i),ix(i+1),…,ix(ndata) の最大値 ix(k) を探す。 c k = i maxval = ix(i) do j= i+1,ndata if(ix(j).gt.maxval) then k = j - 28 - maxval = ix(j) end if end do c c----- ix(i) と ix(k) との値の入れ替え c ia(i) と ia(k) との値の入れ替え ixi = ix(i) ix(i) = ix(k) ix(k) = ixi iai = ia(i) ia(i) = ia(k) ia(k) = iai c end do * return end [実行結果] [dipfr:te007|12]frt ex510.f [dipfr:te007|13]a.out データ数を入力しなさい。 6 ia(1),ix(1),ia(2),ix(2),… を入力しなさい。 101,3 102,63 201,15 202,1 203,31 301,7 整列後のデータ 102 63 203 31 201 15 301 7 101 3 202 1 [dipfr:te007|14] - 29 - [ 演習問題 ( 第5回 ) ] [ 例題5 ] §5の2つの例題プログラムを打ち込んで実行し,実行結果がテキストと同じになる か確かめなさい. [ 演習5 - 1 ] 三角形の3つの頂点の座標を読み込んで,面積と3つの角度を求めるプログラムを作 りなさい.但し,以下の3つの手続きを1つずつサブルーチンにし,メインプログラムで は3つのサプルーチンを呼ぶだけにしなさい. (1)三角形の3つの頂点の座標 (x 1, y 1), (x 2, y 2), (x 3, y 3) を読み込んで印字する. (2)面積 S と3つの角度を計算する. (3)面積と3つの角度を印字する. [ 演習5 - 2 ] l×m 行列 A とm×n 行列 B の行列要素を配列に読み込んで,行列の積 C = A×B の行 列要素を計算するプログラムを作成しなさい.但し,以下の3つの手続きを1つずつサブ ルーチンとし,メインプログラムでは3つのルーチンを呼ぶだけにしなさい.入力する変 数及び配列は l, m, n と行列 A, B の配列要素である. (1)l, m, n と行列 A, B の行列要素を読み込む. (2)積行列 C の行列要素を計算する. (3)C の行列要素を印字する. 変数名や配列名は必ず3文字以上を使用してください. ex.) A → adim l →lsize m →msize B → bdim n →nsize C → cdim - 30 - §6 コンパイラ指示文 - include 文 例 題 §1の例題を次の3つの手続きを用いて実現する. 読み込み:2つのデータa, b を読み込み,印字する. 計 算 :a と b とから,和 s,差 d,積 p,商 qを求める. 印 刷 :計算結果 s, d, p, q を印字する. これら3つの手続きをそれぞれサブルーチンにして,1つの主プログラムでこれ を使う形にプログラムする. 文 法 include 文,コンパイラ指示文 [プログラム] {ファイル main0.f} include 'input' include 'calcu' include 'outpt' *----------------------------------------------------------------------* main0.f in sec6 * * << include 文の練習 >> * * programmed by A.Kamitani * updated at 1993 05/07 *----------------------------------------------------------------------program ex600 call input call calcu call outpt stop end {ファイル input} *----------------------------------------------------------------------* input in sec6 * * データ入力用サブルーチン * * programmed by A.Kamitani * updated at 1993 05/07 * version 1.1 at 1998 10/08 *----------------------------------------------------------------------subroutine input include 'cmmn0' 100 format(/'a と b の値を入力しなさい。' ) 200 format(/' a=',1pe12.5,5x,' b=',1pe12.5) write(*,100) read (*, * ) a,b write(*,200) a,b return end - 31 - {ファイル calcu} *----------------------------------------------------------------------* calcu in sec6 * * 四則演算を実行するサブルーチン * * programmed by A.Kamitani * updated at 1993 05/07 *----------------------------------------------------------------------subroutine calcu include 'cmmn0' s=a+b d=a-b p=a*b q=a/b return end {ファイル outpt} *----------------------------------------------------------------------* outpt in sec6 * * 計算結果の出力用サブルーチン * * programmed by A.Kamitani * updated at 1993 05/07 * version 1.1 at 1998 10/08 *----------------------------------------------------------------------subroutine outpt include 'cmmn0' 100 format(/'和=',1pe12.5,5x,'差=',1pe12.5 & /'積=',1pe12.5,5x,'商=',1pe12.5) write(*,100) s,d,p,q return end {ファイル cmmn0} common/coinp/a,b common/coout/s,d,p,q [実行結果] [dipfr:te007|98]frt main0.f [dipfr:te007|99]a.out a と b の値を入力しなさい. 1.0,2.0 a= 1.00000e+00 和= 3.00000e+00 積= 2.00000e+00 b= 2.00000e+00 差=-1.00000e+00 商= 5.00000e-01 [dipfr:te007|100] - 32 - [ 演習問題 ( 第6回 ) ] [ 例題6 ] テキストの§6の例題を打ち込んで実行し,実行結果がテキストと同じになるか確 かめなさい. [ 演習6 - 1 ] n 個のデータ x 1, x 2, …, x n がある.データの個数 n とデータを逐次読み込んで,それ らを小さい順に並べ替えて出力するプログラムを作成しなさい.但し,以下の3つの手続 きを1つずつサブルーチンとし,主プログラムでは3つのサブルーチンを呼ぶだけにしな さい.尚,プログラム単位はそれぞれ1つのファイルに格納し,主プログラムの先頭に include するようにしなさい. (1)データ数 n とデータ x 1, x 2, …, x n を読み込む. (2)データを小さい順に並べ替える. (3)並べ替えたデータを出力する. データを小さい順に並べ替えるには,以下のようにすればよい. 次の操作を j =1, 2, …, n について繰り返す. (1)x j , x j+1, …, x n の最小値 x k を探す. (2)x k と x j を入れ替える. - 33 - §7 サブルーチン副プログラム -2 7.0 2次方程式 例 題 2次方程式 ax2 + bx + c = 0 を解くプログラムを作り,主プログラムではこのサ ブルーチンを用いて一群の2次方程式を解き,データと答えを印字する.主プ ログラムとサブルーチンとの間のデータの受渡は引数による.係数 a, b, c を引 数 a, b, c を通じて主プログラムからサブルーチンに引き渡し,答えは,引 数 x1, x2, ind を通じて主プログラムに返す(実解のときは ind=1 として, 2解そのものを x1, x2 に入れて返し,共役虚数解のときは ind=2 として, x1 に実数部を x2 に虚数部を入れて返す.a=0, b≠0 のときは ind=3 とし, 唯一の有限な解を x1 に入れて返す.a=b=0 のときは ind=4 として返す). 文 法 実引数,仮引数,引数による結合,stop 文に続く文字列,data 文,p 変換 [プログラム] {ファイル main0.f} include 'quade' include 'outpt' *----------------------------------------------------------------------* main0.f in sec7 * * 2次方程式の解を求める * * programmed by A.Kamitani * version 1.0 at 1993 05/11 * version 1.1 at 1998 06/01 *----------------------------------------------------------------------program main0 100 format(//' **** Solution of Quadratic Equation **** '// & ' :方程式の数を入力しなさい. ') 150 format(/ ' :2次方程式の係数 a, b, c を入力しなさい.') * *----- 方程式数の入力 * write(*,100) read (*, * ) n * do i=1,n c c----係数の入力 c write(*,150) read (*, * ) a,b,c c c----解の計算 c call quade(a,b,c,x1,x2,ind) c c----計算結果の出力 c call outpt(x1,x2,ind) end do * stop ' *** 正常終了! ***' - 34 - end {ファイル quade} *----------------------------------------------------------------------* quade in sec7 * * 2次方程式を解くサブルーチン * * 引数 * [input] * a,b,c : 2次方程式の係数 * [output] * x1,x2 : 解 * ind : 1---2つの実数解をもつ場合 * 2---共役虚数解をもつ場合 * 3---1次方程式になる場合 * 4---解の存在が問題になる場合 * * programmed by A.Kamitani * updated at 1993 05/11 *----------------------------------------------------------------------subroutine quade(a,b,c,x1,x2,ind) data zero,two,four/0.0,2.0,4.0/ if(a.ne.zero) then * *----- 方程式が2次方程式の場合 * d = b**2-four*a*c c if(d.ge.zero) then cc cc---実数解をもつ場合 cc x1 = (-b+sqrt(d))/two/a x2 = (-b-sqrt(d))/two/a ind = 1 return else cc cc---共役虚数解をもつ場合 cc x1 = -b/two/a x2 = sqrt(-d)/two/a ind = 2 return end if c else * *----- 方程式が2次方程式にならない場合 if(b.ne.zero) then cc cc---1次方程式の場合 cc x1 =-c/b ind = 3 return cc else cc - 35 - 解の存在が分からないとき cc---cc ind = 4 return cc end if c end if * end {ファイル outpt} *----------------------------------------------------------------------* * outpt in sec7 * * 解を出力するサブルーチン * * 引数 * [input] * z1,z2 : 解 * ind0 : 1, 2つの実数解をもつ * 2, 共役虚数解をもつ * 3, 1次方程式になる * 4, 解の存在が問題になる * * progammed by A.Kamitani * version 1.0 at 1993 05/11 * version 1.0 at 1998 06/01 *----------------------------------------------------------------------subroutine outpt(z1,z2,ind0) 100 format('解:',1pe13.6,', ',1pe13.6 ) 200 format('解:',1pe13.6,'+-',1pe13.6,'i') 300 format('解:',1pe13.6,', 無限大 ') 400 format(' a = b = 0 ? ') if (ind0.eq.1) then write(*,100) z1,z2 else if (ind0.eq.2) then write(*,200) z1,z2 else if (ind0.eq.3) then write(*,300) z1 else write(*,400) end if return end - 36 - [実行結果] [dipfr:te007|11]frt main0.f [dipfr:te007|12]a.out **** Solution of Quadratic Equation **** :方程式の数を入力しなさい. 4 :2次方程式の係数 a, b, c を入力しなさい. -2.0,-2.0,1.0 解:-1.366025e+00, 3.660254e-01 :2次方程式の係数 a, b, c を入力しなさい. 0.0,-2.0,1.0 解: 5.000000e-01, 無限大 :2次方程式の係数 a, b, c を入力しなさい. 1.5,-2.0,1.0 解: 6.666667e-01+- 4.714045e-01i :2次方程式の係数 a, b, c を入力しなさい. 0.0,0.0,1.0 a = b = 0 ? jwe0002i stop *** 正常終了! *** [dipfr:te007|13] - 37 - [ 演習問題 ( 第7 _ 0回 ) ] [ 例題7 - 0 ] テキストの7.0節の例題を打ち込んで実行し,実行結果がテキストと同じになるか確 かめなさい. [ 演習7 - 1 ] 西暦で表した年数を明治,大正,昭和,平成の年数に変換する引数付きのサブルー チン副プログラムを作成し,同サブルーチンを用いて n 個の年数を明治,大正,昭和,平 成に変換して印字するプログラムを完成しなさい.但し,明治,大正,昭和,平成の元年 はそれぞれ 1868 年,1912 年,1926 年,1989 年である.尚,サブルーチンの引数として 1867 年以前の年数が入力された場合には,サブルーチンが **** abnormal end in (サブルーチン名) **** とメッセージを出して異常終了するようにしなさい. [ 演習7 - 2 ] 三角形の3つの辺の長さから面積を計算する引数付きのサブルーチン副プログラム を作成し,同サブルーチンを用いて,n 個の三角形の面積を計算するプログラムを完成し なさい.但し,サブルーチンの引数である3つの辺の長さ a, b, c として, を満たさないものが入力された場合には,サブルーチン内で **** abnormal end in (サブルーチン名) **** とメッセージを出して異常終了するようにしなさい. - 38 - 7.1 多項式とその導関数の計算 解 説 n 次多項式 (1) の値は,漸化式: (2) (3) を用いて計算される pn(x) の値と等しい.この性質を用いて n 次多項式の値を計 算する方法が Horner の方法であった(3.1 節参照).ここでは,多項式 pn(x) の 導関数の値を計算する方法を考えよう. 式(3) の両辺を x で微分すると, (4) を得る.ここで,多項式 pj (x) の導関数を とおくと, 式(5.1.4) は (5) となる.また,定義より明らかなように,q1(x) = a0 である.式(5) は漸化式を 用いて,多項式 p(x) の導関数が計算できることを示している. 例 題 x の値を与えたとき,p(x) と p¢(x) とを計算するサブルーチン副プログラムを作 成する.多項式の係数は配列 adim に記憶され,引数によってサブルーチンに 引き渡される. 3.1 節と同様に,x min, x max 及び ndiv を与えたとき,x min と x max の間の ndiv 等 分点における p(x), p¢(x) の値を求める. 文 法 擬似寸法配列,引数としての配列名,parameter 文,common 文によるデータの受 け渡しと引数によるデータの受け渡しの使い分け input main0.f cntrl evapd Fig. 7.1. プログラム単位間の参照関係 - 39 - {ファイル main0.f} include 'cntrl' include 'evapd' include 'input' *------------------------------------------------------------------* main0.f in sec7_1 * * programmed by A.Kamitani * version 1.0 at 1993 05/10 * version 1.1 at 1998 06/01 *------------------------------------------------------------------program main0 call input call cntrl stop end {ファイル input} *----------------------------------------------------------------------* input in sec7_1 * * programmed by A.Kamitani * version 1.0 at 1993 05/10 * version 1.1 at 1998 06/01 *----------------------------------------------------------------------subroutine input include 'cmmn0' 100 format(/'Input order of polynomial!' ) 110 format(//'**** parameter error in input.' & /' ncoef > nmax' & /' ncoef =',i4,4x,'nmax =',i4 ) 120 format(/'Input coefficients of polynomial in asscending order!' ) 130 format(/'Input interval in which evaluation is to be performed!') 140 format(/'Input division number of interval!' ) 150 format(//'**** parameter error in input.' & /' ndiv > nxmx' & /' ndiv =',i4,4x,'nxmx =',i4 ) * *----- Input data from system standard input * write(*,100) read (*, * ) ncoef c c----- parameter check against out-of-range error. c if(ncoef.gt.nmax) then write(*,110) ncoef,nmax stop ' **** abnormal end in input ' end if c write(*,120) read (*, * ) (adim(j),j=0,ncoef) write(*,130) read (*, * ) xmin,xmax write(*,140) read (*, * ) ndiv c c----- parameter check against out-of-range error. c if(ndiv.gt.nxmx) then - 40 - write(*,150) ndiv,nxmx stop ' **** abnormal end in input ' end if * *----- determination of x-coordinate at which * polynomial and its derivative are to be calculated. * delx = (xmax-xmin)/float(ndiv) * do j=0,ndiv xval(j) = xmin+delx*float(j) end do * return end {ファイル cntrl} *----------------------------------------------------------------------* cntrl in sec7_1 * * programmed by A.Kamitani * version 1.0 at 1998 06/01 *----------------------------------------------------------------------subroutine cntrl include 'cmmn0' 100 format &(//3x,'j',5x,'value of x',5x,'polynomial',5x,'derivative') 200 format( i4,3(2x,1pe13.6) ) * *----- evaluation of polynomial and its derivative * write(*,100) do j=0,ndiv call evapd(ncoef,adim,xval(j),pval,qval) write(*,200) j,xval(j),pval,qval end do * return end {ファイル evapd} *----------------------------------------------------------------------* evapd in sec7_1 * * evaluation of values of polynomial and its derivative * ~ ~~ ~ ~ * 引数 * [input] * n : 多項式の次数 * adim : 多項式の係数が格納されている配列名 * xval : 評価すべき x の値 * [output] * pval : 多項式の値 * qval : 多項式の微係数の値 * * programmed by A.Kamitani * version 1.0 at 1993 05/10 * version 1.1 at 1998 06/01 *----------------------------------------------------------------------subroutine evapd(n,adim,xval,pval,qval) - 41 - dimension adim(0:*) * pval = adim(0) qval = adim(0) do j=1,n-1 pval = pval*xval+adim(j) qval = qval*xval+pval end do pval = pval*xval+adim(n) return end {ファイル cmmn0} parameter ( nmax = 100 , nxmx = 200 ) common/coeff/adim(0:nmax),ncoef common/evalu/xval(0:nxmx),ndiv [実行結果] [dipfr:te007|51]frt main0.f [dipfr:te007|52]a.out Input order of polynomial! 3 Input coefficients of polynomial in asscending order! 256.0,-130.0,1.0,2.0 Input interval in which evaluation is to be performed! -1.0,1.0 Input division number of interval! 10 j value of x 0 -1.000000e+00 1 -8.000000e-01 2 -6.000000e-01 3 -4.000000e-01 4 -2.000000e-01 5 0.000000e+00 6 2.000000e-01 7 4.000000e-01 8 6.000000e-01 9 8.000001e-01 10 1.000000e+00 [dipfr:te007|53] polynomial -3.850000e+02 -2.130720e+02 -1.006960e+02 -3.558400e+01 -5.447999e+00 2.000000e+00 -9.520009e-01 -2.016000e+00 1.109600e+01 5.067202e+01 1.290000e+02 derivative 1.029000e+03 7.005200e+02 4.334800e+02 2.278800e+02 8.371999e+01 1.000000e+00 -2.028000e+01 1.987999e+01 1.214800e+02 2.845201e+02 5.090000e+02 7.2 行列の和 例 題 2つの l×m 行列 A と B との和行列 C を計算するサブルーチン副プログラムを 作成する.行列要素 ai j, bi j はそれぞれ配列 adim, bdim に記憶され,引数と してサブルーチンに引き渡される. 文 法 整合配列,整合寸法,* を用いた出力,配列の記憶順序 - 42 - input main0.f cntrl calam Fig. 7.2. プログラム単位間の参照関係 {ファイル main0.f} include 'input' include 'calam' include 'cntrl' *----------------------------------------------------------------* main0.f in sec7_2 * * 行列の和を計算する. * * programmed by A.Kamitani * version 1.0 at 1993 05/10 * version 1.1 at 1998 06/01 *----------------------------------------------------------------program main0 call input call cntrl stop end {ファイル input} *----------------------------------------------------------------------* input in sec7_2 * * input data from system standard input * ~~~~~ * programmed by A.Kamitani * version 1.0 at 1993 05/10 * version 1.1 at 1998 06/02 *----------------------------------------------------------------------subroutine input include 'cmmn0' 100 format(/'行列のサイズを l×m とするとき,l,m を入力せよ.') 200 format(/'**** parameter error in input. ' & /' lsize > lmax or msize > mmax ' & /' lsize =',i4,3x,' msize =',i4 & /' lmax =',i4,3x,' mmax =',i4 ) 300 format(20(2x,1pe12.5) ) * *----- 行列のサイズの入力 * write(*,100) read (*, * ) lsize,msize c c----- パラメター・チェック c if(lsize.gt.lmax .or. msize.gt.mmax) then write(*,200) lsize,msize,lmax,mmax stop '**** abonormal end in input.' end if * *----- 行列要素の入力 * - 43 - write(*, * ) ' ' write(*, * ) '行列 A の行列要素を行ごとに入力しなさい!' do i=1,lsize read (*, * ) (adim(i,j),j=1,msize) end do * write(*, * ) ' ' write(*, * ) '行列 B の行列要素を行ごとに入力しなさい!' do i=1,lsize read (*, * ) (bdim(i,j),j=1,msize) end do * *----- 入力データの echo back * write(*, * ) ' ' write(*, * ) '行列 A:' do i=1,lsize write(*,300) (adim(i,j),j=1,msize) end do * write(*, * ) ' ' write(*, * ) '行列 B:' do i=1,lsize write(*,300) (bdim(i,j),j=1,msize) end do * return end {ファイル calam} *----------------------------------------------------------------------* calam in sec7_2 * * calculation of addition of matrices * ~~~ ~ ~ * 引数 * [input] * lmax : 行列 A,B,C の整合寸法 * lsize : 行数 * msize : 列数 * adim,bdim : 行列要素を格納している配列 * [output] * cdim : 和行列の要素を格納している配列 * programmed by A.Kamitani * version 1.0 at 1993 05/10 * version 1.1 at 1998 06/01 *----------------------------------------------------------------------subroutine calam(lmax,lsize,msize,adim,bdim,cdim) dimension adim(lmax,*),bdim(lmax,*),cdim(lmax,*) 100 format(/' **** parameter error in calam.' & /' lsize > lmax ' & /' lsize =',i4,2x,'lmax =',i4) * *----- parameter check against out-of-range error. * if(lsize.gt.lmax) then write(*,100) lsize,lmax stop ' **** abnormal end in calam. ' end if * - 44 - *----- addition of two matrices. * do i=1,lsize do j=1,msize cdim(i,j) = adim(i,j)+bdim(i,j) end do end do * return end {ファイル cntrl} *----------------------------------------------------------------------* cntrl in sec7_2 * * 計算結果の出力 * * 引数 * [input] * lmax : 配列 cdim の整合寸法 * lsize : 配列 cdim の行数 * msize : 配列 cdim の列数 * cdim : 印字すべき計算結果 * * programmed by A.Kamitani * version 1.0 at 1993 05/10 * version 1.1 at 1998 06/01 *----------------------------------------------------------------------subroutine cntrl include 'cmmn0' 100 format(20(2x,1pe12.5)) * *----- addition of two matrices. * call calam(lmax,lsize,msize,adim,bdim,cdim) * *----- output results of computations into system standard output. * write(*, * ) ' ' write(*, * ) '行列和 C:' do i=1,lsize write(*,100) (cdim(i,j),j=1,msize) end do * return end {ファイル cmmn0} parameter ( lmax = 20, mmax = 20 ) common/matrx/adim(lmax,mmax),bdim(lmax,mmax),cdim(lmax,mmax), & lsize,msize,nsize - 45 - [実行結果] [dipfr:te007|1]frt main0.f [dipfr:te007|2]a.out 行列のサイズを l×m とするとき,l,m を入力せよ. 3,3 行列 A の行列要素を行ごとに入力しなさい! 1,2,3 2,3,1 3,1,2 行列 B の行列要素を行ごとに入力しなさい! 4,5,6 5,6,4, 6,4,5 行列 A: 1.00000e+00 2.00000e+00 3.00000e+00 2.00000e+00 3.00000e+00 1.00000e+00 3.00000e+00 1.00000e+00 2.00000e+00 5.00000e+00 6.00000e+00 4.00000e+00 6.00000e+00 4.00000e+00 5.00000e+00 C: 5.00000e+00 7.00000e+00 7.00000e+00 9.00000e+00 9.00000e+00 5.00000e+00 [dipfr:te007|3] 9.00000e+00 5.00000e+00 7.00000e+00 行列 B: 4.00000e+00 5.00000e+00 6.00000e+00 行列和 - 46 - [ 演習問題 ( 第7 _ 1回 ) ] [ 例題7 - 1 ] テキストの7.1節と7.2節の例題を打ち込んで実行し,実行結果がテキストと同じ になるか確かめなさい. [ 演習7 - 3 ] 2つの n 次元ベクトル: がある.次元数 n と2つのベクトル a, b の成分を読み込んで,2つのベクトルのなす角 度を計算するプログラムを作成しなさい.但し,次の3つの手続きを1つずつサブルーチ ンとし,主プログラムでは手続き(1),(2)を行う2つのサブルーチンを呼ぶだけに しなさい.また,手続き(3)を引数付きサブルーチンとして作成し,その中で擬似寸法 配列か整合配列を用いなさい. (1)次元数 n と2つのベクトルの成分をキーボードから読み込む. (2)2つのベクトルのなす角度を手続き(3)を呼ぶことにより計算し,結果を出力す る. (3)次元数 n と2つのベクトルの成分からベクトルのなす角度を計算する. 2つの n 次元ベクトルのなす角度 q は で定義される.ここで,ノルム||と内積()は以下の様に定義している. [ 演習7 - 4 ] l×m 行列 A とm×n 行列 B の行列要素を配列に読み込んで,行列の積 C = A×B の行 列要素を計算するプログラムを作成しなさい.但し,以下の3つの手続きを1つずつサブ ルーチンとし,主プログラムでは手続き(1),(2)を行う2つのサブルーチンを呼ぶ だけにしなさい.また,手続き(3)を引数付きサブルーチンとして作成し,その中で擬 似寸法配列か整合配列を用いなさい. (1)l, m, n と行列 A, B の行列要素を読み込む. (2)積行列 C を手続き(3)を呼ぶことにより計算し,結果を出力する. (3)l, m, n と行列 A, B の行列要素から積行列 C の行列要素を計算する. サブルーチン(3)の引数は3つの行列 A, B, C の整合寸法と l, m, n, A, B, C である. - 47 - 応用例 §8 - 差分法による常微分方程式の境界値問題の解法 8.1 差分法とは? 区間 [a, b] を n 等分してできる n+1 個の分点を のように名付ける.ここで,Dx ∫ (b - a)/n である.関数 y(x) の値が分点 x 0, x 1, …, x n 上 でだけ分かっているとし,y j ∫ y(x j ) と書くことにする.以下では, y'(x j ) 及び y''(x j ) の値 を y 0, y 1, …, y n を用いて表すことを考えよう. 先ず,y(x j ± 1) を x = x j の回りで Taylor 展開することにより,以下の2式を得る. (1) (2) が成り立つ.式(1), (2) から y¢¢(x j ) を消去すると, を得る.即ち, (3) となる.式(3) は,x = x j に於ける関数 y(x) の1階導関数が で近似でき,しかも,近似誤差が O(Dx 2) 程度であることを意味している.全く同様に式 (1), (2) から y'(x j ) を消去することにより,x = x j に於ける関数 y(x) の2階導関数が, で近似でき,しかも,近似誤差が O(Dx 2) 程度であることがわかる(簡単な計算ですから 自分で確かめてみなさい). 以上をまとめると, (4) (5) という近似公式が得られたことになる.このように離散的な位置 x 0, x 1, …, x n での関数 値 y 0, y 1, …, y n を用いて微係数や定積分の値を近似する方法を差分法と呼ぶ. - 48 - 8.2 常微分方程式の境界値問題の数値解法 ここでは,境界値問題: (6) (7) (8) y(0) = 0 , y(p/2) = 1 , を差分法を用いて解いてみよう. 8.2.1 差分化された境界値問題 先ず,区間 [0, p/2] を n 等分して,n+1 個の分点: を得る.但し,Dx ∫ p / 2n である.このとき,x = x j に於いて式(6)を差分近似すると, (9) が得られる.次に,境界条件(7),(8)の差分形式を考えよう.容易にわかるように,式(7),(8) は y0 = 0 , (10) yn = 1 , (11) となる. 方程式 (9), (10), (11) は全部で n+1 本の方程式より構成されており,未知数が y 0, y 1, …, y n の n+1 個となっている.方程式の数と未知数の数が等しいため,この方程式系は, 閉じていることになる.近似解法では,この n+1 元連立方程式を解くことになるのである. 8.2.2 n+1 元連立方程式の反復解法 (a) Jacobi 法 ここでは,連立方程式(9), (10), (11) を反復法を用いて解いてみよう.先ず,式(9) を y j について解き直すと, (12) が得られる.次に, (13) という漸化式を考える.ここで,superscript (k), (k+1) はそれぞれ k, k+1 回目の反復値を意 味する.この を成分とする n+1 次元ベクトル y (k) を - 49 - で定義すると,数列 が収束したとき,その収束値ベクトル y は差分方程式 (12) を満足しているのは明らかである. [証明] 数列 がベクトル y に収束するとき, が成立する.式(13)の両辺の極限をとった式に上式を代入すると,ベクトル y が差分方程 式(12)を満足することがわかる.Q.E.D. 以上のように,境界条件(10), (11) を満足させながら,漸化式(13) を反復して,差分方 程式(12)の解を求める方法をJacobi の 反 復 法 と呼ぶ. 実際にJacobi 法を用いて,上記境界値問題を解くアルゴリズムを考えてみよう.先ず, 数列 し, の初期値 y (0) を与えなければならない.その際,境界条件(10), (11) を考慮 を満足させる必要がある.他の の値は,適当な値でよい.次に,y (1) を求める.これには,境界条件(10), (11) を考慮し, とした後,式(13) を用いて の値を計算する.このように y (1) が決ま れば,全く同様に y (2) , y (3) , …と定まってゆく.通常,不等式: を満足した場合には,k に関する反復をやめて,y (k+1) を収束値と見做す.以上のアルゴ リズムを大雑把に図示すると,図8.1のようになる. - 50 - パラメタのキーボードからの入力 分割数 :n 最大反復回数:k max 収束判定子 :e 初期値 y (0) の設定 破線部を k = 0, 1, …, kmax -1 まで繰り返す 境界条件の設定 収束判定 図8.1. Jacobi 法を用いたアルゴリズム - 51 - (b) Gauss-Seidel 法 漸化式(13) を j = 1, 2, …, n-1 の順に実行してゆく場合, は既に求まっている.そこで,式(13) の右辺の を計算する時点で の代わりに (k+1) 回目の反復値 を積極的に用いた漸化式: (14) を利用すれば,Jacobi 法よりも収束速度を向上させることができるであろう.漸化式 (14) を用いた反復法を Gauss-Seidel 法 と呼ぶ. (c) 逐次過緩和法(Successive Over-Relaxation method, SOR 法) Gauss-Seidel 法を用いた場合,一回の反復での y j の変化量は, (15) である.この変化量を多少大きめにすると,漸化式: (16) を得る.ここで,w は1以上2以下のパラメターであり,加速係数と呼ばれている.漸化 逐 次 過 緩 和 法 (SOR 法 )と呼ぶ. 式(16) を用いた反復法を逐 - 52 - [ 演習問題 ( 第8回 ) ] [ 演習8 - 1 ] 境界値問題: y(0) = 0 , y(p/2) = 1 , をJacobi 法を用いて解くプログラムを作成しなさい.但し,以下の4つの手続きを1つず つサブルーチンとし,主プログラムでは4つのサブルーチンを呼ぶだけにしなさい. (1)データ n, kmax, e をキーボードから読み込む. を設定する. (2)初期値 (3)図8.1の破線内のループを繰り返す. (4)収束値をディスプレイに出力する. 図1の破線内のループで,y (k+1) を計算するには y (k) だけがわかっていればよい.故 に,これら2つのベクトルに相当する2つの配列を予め用意しておけばよい. 図1の破線内のループを 10 回繰り返す毎に, の値と k の値を印刷するようにしなさい.反復回数 k が 10 の倍数であるか否かは,組み 込み関数 mod を用いて, if(mod(k,10).eq.0) then 等とすればよい.尚,組み込み関数 mod(i1,i2) は i1 を i2 で割った余りを表す. [ 演習8 - 2 ] 上記境界値問題をGauss-Seidel 法を用いて解くプログラムを作成しなさい. [ 演習8 - 3 ] 上記境界値問題をSOR 法を用いて解くプログラムを作成しなさい. - 53 - §9 関数副プログラム 例 題 1次元実数型配列の要素の最大値と最小値を計算する2つの関数副プログラム を作成し,n 個の実数型データ a1, a2, a3, …, an を読み込んで,その最大・最小 値を計算するプログラムを作成しなさい. 文 法 関数副プログラム,関数名,function文,文字型変数,character文, a変換 [プログラム] {ファイル main0.f} include 'input' include 'cntrl' include 'dtmn1' include 'dtmx1' include 'ermsg' *----------------------------------------------------------------------* main0.f in sec8 * * データの最大・最小値を求める。 * * programmed by A.Kamitani * version 1.0 at 1993 05/11 * version 1.1 at 1998 06/01 *----------------------------------------------------------------------program main0 call input call cntrl stop end {ファイル input} *----------------------------------------------------------------------* input in sec09 * * programmed by A.Kamitani * version 1.0 at 1998 06/01 *----------------------------------------------------------------------subroutine input include 'cmmn0' * *----- データの入力 * write(*,*) 'データの個数を入力せよ! ' read (*,*) ndata c c----- parameter check against out of range error. c call ermsg(ndata,nmax ,'input','ndata','nmax ') * write(*,*) 'データを入力せよ! ' read (*,*) (adim(n),n=1,ndata) * return end - 54 - {ファイル cntrl} *----------------------------------------------------------------------* cntrl in sec09 * * programmed by A.Kamitani * version 1.0 at 1998 06/02 *----------------------------------------------------------------------subroutine cntrl include 'cmmn0' 100 format(/'maximum of array elements:',1pe12.5 & /'minimum of array elements:',1pe12.5) * *----- 最大・最小値の探索 * rmax = dtmx1(ndata,adim) rmin = dtmn1(ndata,adim) * *----- 計算結果の出力 * write(*,100) rmax,rmin * return end {ファイル dtmx1} *----------------------------------------------------------------------* dtmx1 in sec8 * * 1次元配列の最大値を計算する関数副プログラム * * determinating maximum value of 1 dimensional array * ~ ~ ~ ~ ~ * programmed by A.Kamitani * version 1.0 at 1993 05/11 * version 1.1 at 1998 06/01 *----------------------------------------------------------------------real function dtmx1(ndata,adim) dimension adim(*) * dtmx1 = adim(1) do n=2,ndata dtmx1 = max(dtmx1,adim(n)) end do * return end {ファイル dtmn1} *----------------------------------------------------------------------* dtmn1 in sec8 * * 1次元配列の最小値を計算する関数副プログラム * * determinating minimum value of 1 dimensional array * ~ ~ ~ ~ ~ * programmed by A.Kamitani * version 1.0 at 1993 05/11 * version 1.1 at 1998 06/02 *----------------------------------------------------------------------- - 55 - real function dtmn1(ndata,adim) dimension adim(*) * dtmn1 = adim(1) do n=2,ndata dtmn1 = min(dtmn1,adim(n)) end do * return end {ファイル ermsg} *----------------------------------------------------------------------* ermsg in sec9 * * output error messages about argument check. * * arguments * 入力データ * nval : チェックする変数 * nlim : 許容限界 * srtnm : 本ルチーンを呼んでいるルーチンの名前 (文字型) * valnm : variable name of nval (文字型) * limnm : variable name of nlim (文字型) * * programmed by A.Kamitani * updated at 1991 03/23 *----------------------------------------------------------------------subroutine ermsg(nval,nlim,srtnm,valnm,limnm) character*(*) srtnm,valnm,limnm 100 format(' ',' ++++ parameter error in ',a,'.') 110 format(' ',' ',a,' > ',a ) 120 format(' ',2(' ',a,' =',i5) ) 130 format(' ',' ++++ abnormal end in ',a,'.') * if(nval.gt.nlim) then write(*,100) srtnm write(*,110) valnm,limnm write(*,120) valnm,nval ,limnm,nlim write(*,130) srtnm stop end if * return end {ファイル cmmn0} parameter ( nmax = 100 ) common/codata/adim(nmax),ndata - 56 - [実行結果] [dipfr:te007|84]frt main0.f [dipfr:te007|85]a.out データの個数を入力せよ! 4 データを入力せよ! -999.0,555.4,-1.0e5,2.0e3 maximum of array elements: 2.00000e+03 minimum of array elements:-1.00000e+05 [dipfr:te007|86] [ 演習問題 ( 第9回 ) ] [ 例題9 ] テキストの§9の例題を打ち込んで実行し,実行結果がテキストと同じになるか確 かめなさい. [ 演習9 - 1 ] 2分法を用いて,超越方程式: の解のうち,x Œ (0, p) を満たすものを求めなさい.但し,関数: は関数副プログラムとして定義しなさい.また,解が含まれている区間(本問題では (0, p))と超越方程式の右辺の値を入力引数として解を計算するサブルーチン副プログラムを 作成し,主プログラムでこのサブルーチンを呼び出しなさい. f(x) = c の解が区間 [x 0, x 1] 内にあることが分かっているとき,解を数値的に計算する には次の操作を繰り返せばよい. (1)x 2 = (x 0+x 1)/2 で区間の中点を求める. (2)[f(x 0)-c][f(x 2)-c] を計算する. (3)この値が負または0のときには,解が区間 [x 0, x 2] 内に存在することになるので, x 1 ← x 2 として(1)に戻る.[f(x 0)-c][f(x 2)-c] > 0 のときには,解が区間 [x 2, x 1] 内に存 在することになるので,x 0 ← x 2 として(1)に戻る. 上記操作を繰り返して行けば,解が存在する区間 [x 0, x 1] はみるみる内に狭まって行くの で, - 57 - を満たすようになったら,x 0 を解と見做す. [ 演習9 - 2 ] で定義される関数を Bessel 関数と呼ぶ.この関数の値を計算する関数副プログラムを作成 し,n, x を読み込んで 同関数副プログラムを用いて Bessel 関数の値を計算しなさい. - 58 - §11 ファイル処理 11.1 外部ファイルとレコード フロッピーディスクやハードディスクはキーボードやプリンタに比べて高速な入出力が 可能であり,また大量のデータを記憶することができる.このため,内部記憶装置(メモ リ)で処理しきれない多量なデータを扱うための一時的な保存場所として使用されたり, 大量の計算結果を保存するために用いられる.フロッピーディスクやハードディスクのよ 外 部 フ ァ イ ル と呼ぶ. うな外部媒体上に格納されるファイルを外 一般に,ファイルは図11.1の様に一行ずつの記録から構成される.一行に記述されてい レ コ ー ド と呼ぶ.Fortran では,write 文を一回実行すれば1個のレコードをフ る記録をレ ァイルに書き込んだことになり,read 文を一回実行すれば1個のレコードを読み出した ことになる.例えば, write(11,100) (adim(i),i=1,ndata) を実行すると ndata 個のデータから成るレコードを1個書き出すのに対し, do 10 i=1,ndata 10 write(11,100) adim(i) を実行すると1個のデータから成るレコードを ndata 個書き出したことになる.ファイ レ コ ー ド 数 )とレ レ コ ー ド 長 によって決定される.通常, ルの大きさは全レコードの数(レ ファイルの中ではレコードのバイト数はレコードによって異なる.ファイルを作成すると きには,全レコードのバイト数よりもレコード長を大きく指定しなければならない. レコード長 第1レコード 第2レコード 第3レコード レ コ | ド 数 第 n レコード 図11.1 ファイル内部のデータ構造. 塗りつぶした部分は空白を除くデータを示す. 11.2 ファイルとレコードの種類 逐 次 ア ク セ ス フ ァ イ ル (sequential access file) ファイルはそのアクセスの仕方によって逐 直 接 ア ク セ ス フ ァ イ ル (direct access file) の2種類に分類できる.前者ではファイルの と直 先頭から順にレコードが読み書きされるのに対し,後者では各レコードに番号が付けられ ており,その番号を指定してレコードへのアクセスがなされる. ファイルを構成単位であるレコードには,format 文による書式指定に従った文字列と して記録される場合と OS によって定められた内部表現形式に従った値の列として記録さ 書 式 付 き レ コ ー ド (formatted record) と呼ばれ Editor で れる場合の2種類がある.前者は書 書 式 な し レ コ ー ド (unformatted record) と呼ば 中身を見ることができるのに対し,後者は書 れ Editor では中身を見ることが出来ない.1つのファイル内では全てのレコードが書式付 きか書式なしのいずれか一方に統一されていなければならない. - 59 - 11.3 外部ファイルの接続と解除 外部ファイルへのデータの入出力を行なうために read 文や write 文を用いる際には,装 置番号によって入出力装置をコンピュータに認識させている.キーボードやディスプレイ にはそれぞれ装置番号5,6が既に設定されているが,外部ファイルには装置番号が予め 設定されていない. 特定のファイル名をもつ外部ファイルに装置番号を割り当てるには,open 文 が用い られる.open 文は以下の形式をとる. open([unit=]装置番号,file=ファイル名を示す文字列,access=アクセス方法を示す 文字列,form=レコードの種類を示す文字列[,recl=ワード数]) ここで,装置番号にはゼロ以上の整数を指定する.また,アクセス方法,レコードの種類 を示す文字列には,それぞれ表11.1,11.2に示される値を指定する.access 指定子,form 指定子を省略した際には,それぞれ'sequential', 'formatted' の指定があったと見 做される.特に,アクセス方法が直接アクセスの場合にはファイルのレコード長を指定し なければならない.この指定には,書式付きファイルの場合, recl = 文字数と通常書 くのが一般的であり,書式無しファイルの場合, recl = ワード数注1 で指定する.逐次 アクセスの場合には,recl 指定子を省略できる. 表11.1 アクセス方法を示す文字列 アクセス方法 文字列 逐次アクセス 'sequential' 'direct' 直接アクセス 表11.2 レコードの種類を示す文字列 レコードの種類 文字列 書式付きレコード 'formatted' 'unformatted' 書式なしレコード 例えば,test という名前の逐次アクセスファイルを新たに作成して,書式付きレコードを 書き込むためには, open(99,file='test',access='sequential',access='formatted') としておけば,以後装置番号99はファイル test を示すことになる. 装置番号と外部ファイルとの接続を解除するには,close 文 を用いる.close 文は 以下の形式をしている. close([unit=]装置番号) 11.4 外部ファイルへの入出力 (a) 逐次アクセスファイルへの入出力 注1 最も一般的な 32 ビットマシンの場合,整数型データや実数型データは1ワード,倍精度実数型デー タは2ワードである. - 60 - 入力 出力 read (装置番号[,文番号]) レコード write(装置番号[,文番号]) レコード 但し,書式付きレコードを対象としている場合だけ,format 文の文番号を指定しなけれ ばならない. (b) 直接アクセスファイルへの入出力 入力 出力 read (装置番号[,文番号],rec=レコード番号) レコード write(装置番号[,文番号],rec=レコード番号) レコード ここで,レコード番号とは何番目のレコードに入出力を行なうかを示す整数である. 11.5 ファイル位置付け入出力文 外部ファイルが逐次アクセスファイルのときでも,入出力の対象となるレコードの位置 を変えることができる.この機能をもつ fortran 文はファイル位置付け入出力文と呼ばれ, 次の2種類がある. fortran 文 機 能 backspace 装置番号 rewind 装置番号 1レコード分だけ前の位置に戻す 最初のレコードまで戻す - 61 - [ 演習問題(第11回) ] [ 演習11 - 1 ] 次の漸化式: xn+1= yn- 0.97xn+ 5 -5 , 1+x2n yn+1= -0.995 xn , を用いて得られる点列 (x0,y0), (x1,y1), …, (xm,ym) をプロットするプログラムを次の指示 に従って2種類作成しなさい.但し,初項としては(x0,y0)=(1,0)を用い,m には105を採用 しなさい.また,大量のデータを扱うので配列を用いないで外部ファイルを使用しなさい. 1)外部ファイルとして書式付き逐次アクセスファイルを用いなさい. 2)外部ファイルとして書式無し直接アクセスファイルを用いなさい. - 62 -
© Copyright 2024 Paperzz