...

FORTRANプログラミング入門 9回 配列(2),ファイル入出力 - ax

by user

on
Category: Documents
13

views

Report

Comments

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
Fly UP