木村拓馬
FORTRANプログラミング入門–第 9回配列 (2),ファイル入出力–
木村拓馬
2014年6月 7日 15:52
FORTRAN プログラミング入門,–第 9 回配列 (2),ファイル入出力– 1/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 と表示される.
1WRITE(*,’(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) 一次元配列 Aの要素を配列 Sの形状の
多次元配列に配列し直す.
SHAPE(A) 配列 Aの形状を配列として取り出す.
.例 9.4:初期値設定の例..
......
integer :: a(2, 3) = reshape((/6, 5, 4, 3, 2, 1/), (/2, 3/))
integer :: b(2, 3) = reshape((/6, 5, 4, 3, 2, 1/),shape(a))
integer :: c(3, 2) = reshape((/ (i, i = 1, 6) /), (/3, 2/))
integer :: d(3, 2) = reshape((/ (i, i = 1, 6) /), shape(c))
FORTRAN プログラミング入門,–第 9 回配列 (2),ファイル入出力– 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]) 配列 aの (DIM次元方向の)(マスク式 MASKが真の) すべての要素の和.
PRODUCT(a [, DIM, MASK]) 配列 aの (DIM次元方向の)(マスク式 MASKが真の) すべての要素の積.DOT PRODUCT(u, v) 同じ大きさの 1次元配列 u, vのスカラー積 (各要素の積の和).
MATMUL(a, b) 2つの行列の積.TRANSPOSE(a) 2次元行列の転置行列.
SIZE(a [, DIM]) 配列 aの全体 (または DIM次元方向)の要素数.COUNT(m [, DIM]) マスク式 mの (DIM次元方向の)要素のうち真の要素の数.LBOUND(a [, DIM]) 配列 aの (DIM次元方向の)添字の下限値.UBOUND(a [, DIM]) 配列 aの (DIM次元方向の)添字の上限値.
MAXVAL(a [, DIM, MASK]) 配列 aの (DIM次元方向に)(マスク式 MASKが真の) 要素の最大値を要素とする配列.
MINVAL(a [, DIM, MASK]) 配列 aの (DIM次元方向に)(マスク式 MASKが真の) 要素の最小値を要素とする配列.
MAXLOC(a [, MASK]) 配列 aの (マスク式 MASKが真の)要素の最大値の相対位置を表す各次元の添字の値を要素とする 1次元ベクトル配列.
MINLOC(a [, MASK]) 配列 aの (マスク式 MASKが真の)要素の最小値の相対位置を表す各次元の添字の値を要素とする 1次元ベクトル配列.
PACK(a, m) 配列 aのマスク式 mが真の要素を要素順に並べた 1次元配列.UNPACK(a, m, b) 配列 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(*,*) SUM(A) ! 総和
WRITE(*,*) SUM(A, DIM=1) ! 1 次元方向の和
WRITE(*,*) SUM(A, DIM=2) ! 2 次元方向の和
WRITE(*,*) SUM(A, 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”を用意し,
...2 ”file1.txt”からデータを読み込み
...3 読み込んだデータを処理して”file2.txt”に書き込む
.”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_ 1 = 11
Data_ 2 = 22
Data_ 3 = 33
Data_ 4 = 44
Data_ 5 = 55
Data_ 6 = 66
FORTRAN プログラミング入門,–第 9 回配列 (2),ファイル入出力– 16/23
木村拓馬
ファイル操作の例.例 9.10:2次元配列にデータを読み込む..
......
...1 第 1行に”行数”と”列数”,第 2行以降に”データ”を書いたファイル”file3.txt”を用意,
...2 ”file3.txt”からデータを読み込み
...3 画面に表示する
.”file3.txt”の例,スペースで区切る..
......
4␣3
11␣12␣13
21␣22␣23
31␣32␣33
41␣42␣43
.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
FORTRAN プログラミング入門,–第 9 回配列 (2),ファイル入出力– 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
木村拓馬
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)
B = 1
END WHERE
WRITE(*,*) B
.実行すると以下のようになる...
......
1 2 3 4 5 6
1 0 3 0 5 0
0 0 0 0 0 0
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 programFORTRAN プログラミング入門,–第 9 回配列 (2),ファイル入出力– 23/23