Comments
Description
Transcript
FORTRANプログラミング入門 9回 配列(2),ファイル入出力 - ax
木村拓馬 FORTRAN プログラミング入門 –第 9 回 配列 (2),ファイル入出力– 木村拓馬 2014 年 6 月 7 日 15:52 FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 1/23 木村拓馬 . 本日は . 多次元配列 ファイル操作 . (WHERE 文) FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 2/23 木村拓馬 多次元配列 前回紹介した配列は,タテ・ヨコ・ナナメ…と 7 次元までの多次元にできる1 . 配列のイメージ:データを入れる箱(変数)を連結 図 1: スカラ変数 図 2: 一次元配列 図 3: 二次元配列 図 4: 三次元配列 1 配列は,7 次元までの次元をもつことができ,どの次元も任意の 寸法 (extent),すなわち要素の個数 をもつことができる。配列の 次元数 (rank) は,次元の個数とする。配列の 大きさ (size) は,要素の総 数とし,寸法の積に等しい。配列は,大きさがゼロであってもよい。配列の 形状 (shape) は,その次元 数 及び 各次元の寸法によって決定され,それらの寸法を要素とする 1 次元配列として表現することが できる。 FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 3/23 木村拓馬 多次元配列 前回紹介した配列は,タテ・ヨコ・ナナメ…と 7 次元までの多次元にできる2 . . 型宣言, DIMENSION([下限:] 上限, [下限:] 上限, · · · ) :: 配列名 型宣言 :: 配列名 ([下限:] 上限, [下限:] 上限, · · · ) . 1 次元配列同様,下限は省略可能で,省略した場合は 1 . . 例 9.1:型宣言の例 . REAL, DIMENSION(2, 3) :: A REAL :: B(3, 3), C(-2:3, 4) . 上の例のように記述すると, A(1,1), A(2,1), A(1,2), A(2,2), A(1,3), A(2,3) という 6 個の変数, B(1,1), B(2,1), B(3,1), B(1,2), B(2,2), B(3,2), B(1,3), B(2,3), B(3,3), という 9 個の変数, C(-2,1), C(-1,1),· · · , C(3,1), · · · · · · , C(-2,4), C(-1,4),· · · , C(3,4), という 24 個の変数, が用意される. 2 配列は,7 次元までの次元をもつことができ,どの次元も任意の 寸法 (extent),すなわち要素の個数 をもつことができる。配列の 次元数 (rank) は,次元の個数とする。配列の 大きさ (size) は,要素の総 数とし,寸法の積に等しい。配列は,大きさがゼロであってもよい。配列の 形状 (shape) は,その次元 数 及び 各次元の寸法によって決定され,それらの寸法を要素とする 1 次元配列として表現することが できる。 FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 4/23 木村拓馬 入出力 多次元配列 A の要素の入出力の際, . READ(*,*) A WRITE(*,*) A . のように書くときは,タテヨコの順番に注意しないといけない: . 例 9.2: . INTEGER :: I,J INTEGER, DIMENSION(2, 3) :: A READ(*,*) A DO I=1,2 DO J=1,3 WRITE(*,’(I3,$)’) A(I,J) END DO END DO . . 上を実行して 1 2 3 4 5 6 と入力すると, 1 3 5 2 4 6 と表示される. . 1 WRITE(*,’(I3,$)’) の$は,advance=’no’,と同様に改行しないで表示したいとき使用.非標準のよう だがよく見るのでココで紹介.’/ ’もたまに見る. FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 5/23 木村拓馬 入出力 多次元配列は,下図のような一次元配列を並び替えたものと考えることができる3 : 多次元配列のデータの並び ⇔ ⇔ 図 5: 配列要素の順序 先の例では,この順序4 を注意していないので入力と出力の順番が違っている. 3 [1] 配列の 形状 (shape) は,その次元数 及び 各次元の寸法によって決定され,それらの寸法を要素 とする 1 次元配列として表現することができる。 4 [1] でいうところの ”配列要素順序(6.2.2.2 参照)に従った配列要素全体の列 ”. この順序を意識してプログラムすると実行速度が速くなって良い [3] が,本講義では理解しやすさを 重視し,あまり気にしないことにする.教科書 [2] でも気にしていないようであるし. FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 6/23 木村拓馬 初期値設定 READ,WRITE の例では,多次元配列も一次元配列のように扱うことができるように 見えたが,宣言と同時に初期値を設定する際はダメ. . 例 9.3:使えない例 . integer :: a(2, 3) = (/6, 5, 4, 3, 2, 1/) integer :: b(2, 3) = (/ (i, i = 1, 6) /) . 多次元配列に初期値を設定するには,配列を並べなおす組込み関数 RESHAPE を使う. 配列の形状を取り出す SHAPE を組み合わせることもある. 組込み関数 RESHAPE(A, S) SHAPE(A) . 例 9.4:初期値設定の例 . integer integer integer integer . :: :: :: :: a(2, b(2, c(3, d(3, 3) 3) 2) 2) = = = = 意味 一次元配列 A の要素を配列 S の形状の 多次元配列に配列し直す. 配列 A の形状を配列として取り出す. reshape((/6, 5, 4, reshape((/6, 5, 4, reshape((/ (i, i = reshape((/ (i, i = FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 3, 3, 1, 1, 2, 2, 6) 6) 1/), (/2, 3/)) 1/),shape(a)) /), (/3, 2/)) /), shape(c)) 7/23 木村拓馬 代入と演算 配列への値の代入と算術演算は,配列要素を指定して行う. 配列要素を指定しない場合は,ベクトル演算となる (同じ形 (大きさ・次元) の配列でなければならない). . 例 9.5: . integer :: a(3,1) a(1,1) = 2 a(2,1) = 4 a(3,1) = a(1,1) + a(2,1) !a は 2, 4, 6 となる. . . 例 9.6: . integer :: a(3,1) = reshape((/2, 4, 6/), (/3,1/)), & & b(3,1) = reshape((/1, 2, 3/), (/3,1/)), c(3,1) c(1,1) = a(1,1)*b(1,1) c(2,1) = a(2,1)*b(2,1) c(3,1) = a(3,1)*b(3,1) write(*,*) c !c は 2, 8, 18 となる. ! 上の3つの掛け算をまとめて書くと c = a * b write(*,*) c !c は 2, 8, 18 となる. . FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 8/23 木村拓馬 配列関数 配列を効率的に処理できるように,多くの組込み関数 (配列関数) が用意されている. 組込み関数 SUM(a [, DIM, MASK]) PRODUCT(a [, DIM, MASK]) DOT PRODUCT(u, v) MATMUL(a, b) TRANSPOSE(a) SIZE(a [, DIM]) COUNT(m [, DIM]) LBOUND(a [, DIM]) UBOUND(a [, DIM]) MAXVAL(a [, DIM, MASK]) MINVAL(a [, DIM, MASK]) MAXLOC(a [, MASK]) MINLOC(a [, MASK]) PACK(a, m) UNPACK(a, m, b) 意味 配列 a の (DIM 次元方向の)(マスク式 MASK が真の) すべての要素の和. 配列 a の (DIM 次元方向の)(マスク式 MASK が真の) すべての要素の積. 同じ大きさの 1 次元配列 u, v のスカラー積 (各要素の積の和). 2 つの行列の積. 2 次元行列の転置行列. 配列 a の全体 (または DIM 次元方向) の要素数. マスク式 m の (DIM 次元方向の) 要素のうち真の要素の数. 配列 a の (DIM 次元方向の) 添字の下限値. 配列 a の (DIM 次元方向の) 添字の上限値. 配列 a の (DIM 次元方向に)(マスク式 MASK が真の) 要素の最大値を 要素とする配列. 配列 a の (DIM 次元方向に)(マスク式 MASK が真の) 要素の最小値を 要素とする配列. 配列 a の (マスク式 MASK が真の) 要素の最大値の相対位置を表す 各次元の添字の値を要素とする 1 次元ベクトル配列. 配列 a の (マスク式 MASK が真の) 要素の最小値の相対位置を表す 各次元の添字の値を要素とする 1 次元ベクトル配列. 配列 a のマスク式 m が真の要素を要素順に並べた 1 次元配列. 配列 a のマスク式 m が真の要素を要素順に並べ, 偽の位置には b の要素を配置した 1 次元配列. (表中の [ ] は省略可.DIM, MASK は DIM=引数, MASK=引数と記述しなければならない) FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 9/23 木村拓馬 配列関数の使用例 . 例 9.7:総和を計算する関数 SUM . INTEGER :: A(2, 3) = RESHAPE((/ (I, I = 1, 6) /), (/2, 3/)) WRITE(*,*) WRITE(*,*) WRITE(*,*) WRITE(*,*) . SUM(A) SUM(A, SUM(A, SUM(A, ! 総和 DIM=1) ! 1 次元方向の和 DIM=2) ! 2 次元方向の和 MASK=( MOD(A, 2)==1 )) ! 要素中の奇数の和 . . 実行すると 計算結果をたしかめてみる . . 21 3 7 11 9 12 .9 ! ! ! ! . 1+2+3+4+5+6 = 21 a(1,1)+a(2,1)=3, a(1,2)+a(2,2)=7, a(1,3)+a(2,3)=11 a(1,1)+a(1,2)+a(1,3)=9, a(2,1)+a(2,2)+a(2,3)=12 a(1,1)+a(1,2)+a(1,3)=9 FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 10/23 木村拓馬 配列関数の使用例 . 例 9.8: . INTEGER :: SCORE(100) REAL :: AVERAGE SCORE = -1 SCORE(1) = 80 ; SCORE(2) = 100 ; SCORE(3) = 70 ; SCORE(4) = 0 ! 負でない要素を出力 WRITE(*,*) PACK(SCORE, SCORE >= 0) ! 負でない要素の平均を計算して出力 AVERAGE = REAL(SUM(SCORE, MASK=(SCORE >= 0))) / COUNT(SCORE >= 0) .WRITE(*,*) AVERAGE 実行すると . 80 100 70 0 62.50000 . FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 11/23 木村拓馬 ファイル操作(ファイル接続文) 入出力するファイルを開く . . OPEN(装置番号, FILE=’ ファイル名’ [, オプション]) 装置番号は 5, 6 以外の 1∼99 の整数 (5, 6 は標準入出力a で用いられているため,通常は使用しない). ファイル名は,実行時のカレントディレクトリからの相対パス, もしくは絶対パス. 主なオプション IOSTAT=整数変数 正常に処理されたとき 0,エラーが発生したとき正の整数値を返す. STATUS=文字型定数または変数 ファイルが既に存在している場合は’OLD’, 新規に作成する場合は’NEW’, ファイルを使用後消去する場合は’SCRATCH’, 不明の場合には’UNKNOWN’ を指定する. 指定を省略した場合は’UNKNOWN’ とみなされる. ERR=文番号 エラーが発生した場合に文番号の文へ実行を移す. a キーボードと画面 FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 12/23 木村拓馬 ファイル操作 入出力するファイルを閉じる . . CLOSE(装置番号 [, オプション]) 装置番号は OPEN 文で指定した装置番号に対応させる. 主なオプション IOSTAT=整数変数 正常に処理されたとき 0,エラーが発生したとき正の整数値. STATUS=文字型定数または変数 ファイルを保存する場合は’KEEP’,ファイルを消去する場合 は’DELETE’ を指定する.指定を省略した場合は’KEEP’ とみなされる. ただし,OPEN 文で STATUS=’SCRATCH’ を指定した場合は STATUS=’DELETE’ とみなされる. ERR=文番号 エラーが発生した場合に文番号の文へ実行を移す. . ファイルに入出力するときは READ(装置番号, 書式識別子) 変数名 WRITE( 装置番号, 書式識別子) 文字または変数名 . FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 13/23 木村拓馬 ファイル操作の例 . 例 9.9:ファイル操作の例 . 1. ”データの個数 ”と ”データ ”を書いたファイル”file1.txt”を用意し, . ”file1.txt”からデータを読み込み 3. 読み込んだデータを処理して”file2.txt”に書き込む 2 . . ”file1.txt ”の例 . 6 11 22 33 44 55 66 . . ← ← ← ← . データの個数は6個 1つ目のデータ 2つ目のデータ 6つ目のデータ FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 14/23 木村拓馬 ファイル操作の例 . ex9.9.f90 . program openclose implicit none integer :: n, i, a(10), sum=0 open(10, file=’file1.txt’) open(11, file=’file2.txt’) read(10,*) n do i = 1, n read(10,*) a(i) end do do i = 1, n write(11,’(a7,i3,a3,i3)’) ’Data_’, i, ’ = ’, a(i) end do close(10) close(11) end program . FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 15/23 木村拓馬 ファイル操作の例 ex9.9.f90 を実行すると,カレントディレクトリに”file2.txt”ができているはず. . file2.txt . Data_ Data_ Data_ Data_ Data_ . Data_ 1 2 3 4 5 6 = = = = = = 11 22 33 44 55 66 FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 16/23 木村拓馬 ファイル操作の例 . 例 9.10:2 次元配列にデータを読み込む . 1. 第 1 行に ”行数”と”列数 ” , 第 2 行以降に ”データ ” を書いたファイル”file3.txt”を用意, . ”file3.txt”からデータを読み込み 3. 画面に表示する 2 . . ”file3.txt ”の例,スペースで区切る . 4␣3 11␣12␣13 21␣22␣23 31␣32␣33 41␣42␣43 . FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– . ex9.10.f90 . program openclose2 implicit none integer :: n,m,i,j integer :: a(10,10) open(11,file=’file3.txt’) ! 配列のサイズを読み込む read(11,*) n,m ! データを読み込む do i=1,n read(11,*) (a(i,j), j=1,m) end do ! 画面に表示 do i=1,n write(*,*) (a(i,j), j=1,m) end do close(11) end program . 17/23 木村拓馬 参考文献 [1] JIS X 3001-1:2009 (プログラム言語 Fortran – 第 1 部:基底言語) [2] 戸川隼人:ザ・Fortran90/95,サイエンス社(1999) [3] 渡部 善隆: 連立 1 次方程式の基礎知識∼および Gauss の消去法の安定性に ついて∼, 九州大学大型計算機センター広報, Vol.28, No.4 (1995), pp.291-349. FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 18/23 木村拓馬 Appndix FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 19/23 木村拓馬 WHERE 文 配列のある条件を満たす要素だけを選んで変更を加える 単純 WHERE 文 . . WHERE(マスク式) 配列代入文 ブロック WHERE 文 . WHERE(マスク式) 配列代入文 ELSEWHERE(マスク式) 配列代入文 ELSEWHERE 配列代入文 ENDWHERE . WHERE の後に THEN は必要なし. FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 20/23 木村拓馬 WHERE 文 . 例 9.11:WHERE 文の例 . INTEGER :: A(2, 3) = RESHAPE((/ (i, i = 1, 6) /), (/2, 3/)) INTEGER :: B(2, 3) = 0 ! A の要素の中で偶数(2 で割った余りが 0 となる)要素を 0 とする WRITE(*,*) A WHERE(MOD(A, 2) == 0) A = 0 WRITE(*,*) A . 実行すると以下のようになる. . 1 2 3 4 5 6 1 . 0 3 0 5 0 FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 21/23 木村拓馬 WHERE 文 . 例 9.12:続・WHERE 文の例 . INTEGER :: A(2, 3) = RESHAPE((/ (i, i = 1, 6) /), (/2, 3/)) INTEGER :: B(2, 3) = 0 ! A の要素の中で偶数(2 で割った余りが 0 となる)要素を 0 とする WRITE(*,*) A WHERE(MOD(A, 2) == 0) A = 0 WRITE(*,*) A ! A の要素の中で値が 1 の要素に対応する B の要素を 5 とし, ! A の要素の中で値が 3 の要素に対応する B の要素を 3 とし, ! A の要素の中で値が 5 の要素に対応する B の要素を 1 とする. WRITE(*,*) B WHERE(A == 1) B = 5 ELSEWHERE(A == 3) . 実行すると以下のようになる. B = 3 . ELSEWHERE(A == 5) 1 2 3 4 5 6 B = 1 1 0 3 0 5 0 END WHERE 0 0 0 0 0 0 WRITE(*,*) B .5 0 3 0 1 0 . FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 22/23 木村拓馬 ファイルから READ . ex9.13.f90 . program openclose3 implicit none integer :: i=0 real :: x character(255) :: filename write(*,*) ’Input a filename -->’ ! ファイル名をキーボードから read して open read(*,*) filename open(11,file=filename) ! 行数がわからないデータを読み込むときは,read 文に ! ファイルの最後にたどりついた場合の処理を課す do read(11,*,end=100) x !読込が終わったら 100 行に移動 write(*,*) x i=i+1 end do 100 write(*,*) ’\n’, i, ’ 個のデータが見つかりました’ close(11) .end program FORTRAN プログラミング入門,–第 9 回 配列 (2),ファイル入出力– 23/23