配列
次のプログラムはキーボードから5つの整数を読み込んで平均値を計算します。
program work0601 implicit none integer :: n1, n2, n3, n4, n5 write(*,*) 'Input N1:' read(*,*) n1 write(*,*) 'Input N2:' read(*,*) n2 write(*,*) 'Input N3:' read(*,*) n3 write(*,*) 'Input N4:' read(*,*) n4 write(*,*) 'Input N5:' read(*,*) n5 write(*,*) 'Mean = ', (n1 + n2 + n3 + n4 + n5) / 5.0d+0 stop end program work0601
読み込む数字が5ではなく100だったらどうなるでしょう. 数字を記憶しておくために100個の変数を用意するは大変です.
このような場合に役に立つのが「配列 (array)」です. 配列は同じ型の変数の集まりを「添字(そえじ)」と呼ばれる番号で管理します. 配列は次のように宣言します.
integer :: nx(5)
この宣言によって nx は integer 型の変数が5個集まった配列となります.
配列の各要素は,配列の名前に続けて ( )
の中に番号を入れて,
nx(1), nx(2), nx(3), nx(4), nx(5) と表します.
この番号のことを「添字」といいます.
添字は通常,先頭から順に 1, 2, 3, … となります。
5つの要素を持つ配列 nx ┌─┬─┬─┬─┬─┐ │1│2│3│4│5│ └─┴─┴─┴─┴─┘
配列は同一の型を持つ変数の集合です. 配列 nx のどの要素も integer 型の変数であることに注意しましょう.
配列と do 文
5つの要素をもつ integer 型の配列を用意し,先頭から順に 1, 2, 3, 4, 5 を代入して,平均値を表示するプログラムを以下に示します.
program work0602 implicit none integer :: nx(5) ! 配列の宣言 nx(1) = 1 nx(2) = 2 nx(3) = 3 nx(4) = 4 nx(5) = 5 write(*,*) (nx(1) + nx(2) + nx(3) + nx(4) + nx(5)) / 5.0d+0 stop end program work0602
このプログラムを do 文を使って書き換えると次のようになります.
program work0603 implicit none integer :: nx(5), i do i = 1, 5 nx(i) = i end do write(*,*) (nx(1) + nx(2) + nx(3) + nx(4) + nx(5)) / 5.0d+0 stop end program work0603
練習問題
5つの要素をもつ integer 型の配列を用意し,先頭から順に 11, 12, 13, 14, 15 を代入して,平均値を表示するプログラムを作成せよ. do 文を利用すること.
配列の初期化
変数を宣言する際は,明らかに必要のない場合(do 変数など)を除いて初期化すべきです. 変数と同様に,配列も宣言時に初期化することができます. 次の例では,配列の各要素を順に 1, 2, 3, 4, 5 で初期化しています.
program work0605 implicit none integer :: nx(5) = (/ 1, 2, 3, 4, 5 /) ! 配列の初期化 integer :: i do i = 1, 5 write(*,*) nx(i) end do stop end program work0605
(/ 1, 2, 3, 4, 5 /)
のことを「配列生成子」といいます.
また,配列のすべての要素を,あるひとつの値で初期化する場合は,代入文を使って
integer :: nx(5) = 0 ! すべての要素を 0 にする
と書くことができます.
練習問題
5つの要素をもつ integer 型の配列を用意し,先頭から順に 3, 1, 4, 1, 5 で初期化して, 値を表示するプログラムを作成せよ. do 文を利用すること.
配列に値を読み込む
配列の各要素にキーボードから値を読み込み,それを表示するプログラムを示します. 値を読み込むために read 文を利用するのは通常の変数の場合とまったく同様です.
program work0607 implicit none integer :: nx(5), i do i = 1, 5 write(*,*) 'Input nx(', i, ')' read(*,*) nx(i) end do do i = 1, 5 write(*,*) i, nx(i) end do stop end program work0607
次のようにして,配列に一度に値を読み込むことができます.
program work0608 implicit none integer :: nx(5), i write(*,*) 'Input nx(1:5)' read(*,*) nx(1:5) do i = 1, 5 write(*,*) i, nx(i) end do stop end program work0608
read(*,*) nx(1:5)
は次と同じ意味になります.
read(*,*) nx(1), nx(2), nx(3), nx(4), nx(5)
キーボードから値を入力するときは,5つの数字を空白で区切って1行にまとめましょう.
% ./a.out Input nx(1:5) 1 2 3 4 5
配列を逆順に並び替える
配列の値を先頭から順に読み込み,それを逆順に並び替えることを考えてみましょう. nx(1) から nx(5) までの5つの要素を並び替えるには
nx(1) と nx(5) を交換 nx(2) と nx(4) を交換
という作業が必要です. これをプログラムにすると次のようになります.
program work0609 implicit none integer :: nx(5), i, tmp write(*,*) 'Input nx(1:5)' read(*,*) nx(1:5) ! 逆順に並び替える do i = 1, 2 tmp = nx(i) nx(i) = nx(6-i) nx(6-i) = tmp end do do i = 1, 5 write(*,*) i, nx(i) end do stop end program work0609
2つの変数の値を交換するのに
x = y y = x
としてはいけません(x も y も,もとの y の値になってしまいます). ひとつ余分な変数(上の例では tmp)を用意して
tmp = x ! x の値を tmp に保存 x = y ! x に y の値を代入 y = tmp ! y に保存しておいた x の値を代入
とする必要があります.
練習問題
work0609 を書き換えて,配列の要素数を 8 に変更せよ.
配列のコピー
ある配列を別の配列にコピーするには2つの方法があります.
do 文を利用して要素ごとにコピーする方法
program work0611 implicit none integer :: nx(5) = (/ 1, 2, 3, 4, 5 /), ny(5) = 0 do i = 1, 5 ny(i) = nx(i) end do do i = 1, 5 write(*,*) ny(i) end do stop end program work0611
代入文を利用してコピーする方法
program work0612 implicit none integer :: nx(5) = (/ 1, 2, 3, 4, 5 /), ny(5) = 0 ny(1:5) = nx(1:5) ! 配列のコピー do i = 1, 5 write(*,*) ny(i) end do stop end program work0612
代入文を利用する場合,2つの配列の要素数が等しいときは,添字の範囲を省略することができます.
ny = nx
ただし,この書き方では nx, ny が配列なのか,あるいは通常の変数なのか, この部分をみただけでは区別できません. そこで,nx, ny が配列であることが一目でわかるように,
ny(1:5) = nx(1:5)
と書くほうがよいという意見もあります.
練習問題
work0612 を書き換えて,配列 nx の要素の並びを逆順に ny にコピーするプログラムを作成せよ.
最大値を見つける
次の例は,キーボードから5つの整数を入力し,その最大値を求めるプログラムです.
program work0614 implicit none integer :: nx(5), i, tmp write(*,*) 'Input 5 integers:' read(*,*) nx(1:5) ! 最大値を見つける tmp = nx(1) do i = 2, 5 if (nx(i) > tmp) tmp = nx(i) end do write(*,*) tmp stop end program work0614
最大値をみつけるために,仮の最大値として tmp
に nx(1)
の値を代入しておきます.
do ループを使って nx(2)
, nx(3)
, ..., nx(5)
との大小比較を行い,
tmp
より大きい値が見つかったら tmp = nx(i)
によって tmp
の値を更新します.
練習問題
work0614 を書き換えて,最小値を見つけるプログラムを作成せよ.
本日の課題
最小値・最大値を見つける
キーボードから5つの整数を入力し,最小値と最大値を同時に求めるプログラムを作成せよ.
平均値を求める
キーボードから5つの整数を入力し,その平均値を求めるプログラムを作成せよ.
ベクトルの内積
2つの3次元ベクトル x, y をキーボードから読み込み,内積 x.y を計算するプログラムを作成せよ。 x, y は real(8) 型の配列とする. 3次元ベクトルは要素数 3 の配列で表すことができる.