• 検索結果がありません。

部分配列

ドキュメント内 Fortran (2015 ) (ページ 98-101)

第 6 章 配列計算式 90

6.2 部分配列

配列名だけを使った配列計算式では全ての要素について計算をしますが,常に全要素の計算が必要と は限りません.そこで,配列の一部を取り出した配列,“部分配列”を指定することができます.部分配 列は“:” (コロン)を使って要素番号の範囲を指定します.例えば,1次元配列aに対して,

a(n1:n2)

と書けば,a(n1)〜a(n2)というn2-n1+1個の要素から構成された1次元配列として配列計算式に使う ことができます.また,2次元配列bに対して,

b(n11:n12,n21:n22)

と書けば,b(n11,n21)b(n12,n21)b(n11,n22)b(n12,n22)という(n12-n11+1)×(n22-n21+1) 2次元配列として配列計算式に使うことができます.また,ある次元の要素番号を固定して,

b(n,n21:n22)

と書けば,b(n,n21)b(n,n22)というn22-n21+1個の要素から構成された1次元配列として配列計算 式に使うことができます.

逆に,要素番号に“:”だけを記述すると,「その次元の全要素」という意味になります.例えば,

b(:,n21:n22)

と書けば,第1次元は全要素で,第2次元がn21n22の範囲の要素から構成された2次元配列として 配列計算式に使うことができます.このため,全ての要素番号を“:”にすると,配列全体を代表するこ とになります.そこで,全配列要素を使った配列計算式を書くときにも“:”を使って配列であることを 明示することができます.例えば,6.1節の2次元配列計算式,

a = sqrt(b*sin(c)/(3.2*c + 1.5e-3)) は,次のように書くことができます.

a(:,:) = sqrt(b(:,:)*sin(c(:,:))/(3.2*c(:,:) + 1.5e-3))

この方が,単一変数の計算式と区別できるので良いと思います.本書でもこれ以降はこの書式を使って 全要素の配列計算式を記述します.

要素範囲の指定に“:整数値”を追加して,do文のような増分値を指定することもできます.例えば,

1次元配列aに対して,

a(n1:n2:n3)

と書けば,a(n1)a(n1+n3)a(n1+2*n3)...という要素からなる1次元配列として配列計算式に使 うことができます.この場合,終了要素はn2とは限らないので注意して下さい.例えば,次のように書 くことができます.

real a(10),b(5) ...

b(1:5) = a(1:10:2)

この結果は,b(1)=a(1)b(2)=a(3)b(3)=a(5)b(4)=a(7)b(5)=a(9)という5個の代入文と等価 になります.増分値は負数を与えることも可能なので,次のように逆向きに代入させることも可能です.

real a(10),c(10) ...

c(1:10) = a(10:1:-1)

この結果は,c(1)=a(10)c(2)=a(9)...c(10)=a(1)という10個の代入文と等価になります.

配列計算式で部分配列を使うときは,その部分配列がその他の配列と同型であれば良いので,宣言文 での次元や要素数が一致している必要はありません.例えば1次元配列なら,

real a(10),b(5) ...

a(3:5) = b(1:3)**2

のように書くことができます.また,2次元配列の部分配列を使って,

real a(10,10),b(5,4),c(10) ...

a(3:5,6:8) = b(1:3,1:3)**2

などと書くことができます.この配列計算式をdo文で表せば,

do j = 6, 8 do i = 3, 5

a(i,j) = b(i-2,j-5)**2 enddo

enddo

となります.ある次元の要素番号を固定した2次元配列は1次元配列として扱えるので,2次元配列と 1次元配列が混在した計算も可能です.例えば,

real a(10,10),c(10) ...

c(3:8) = a(3,3:8)**2

と書くことができます.この配列計算式をdo文で表せば,

do j = 3, 8

c(j) = a(3,j)**2 enddo

となります.

なお,部分配列を使った配列計算式で,左辺と右辺に同じ配列を使う場合には,単純にdo文で置き換 えた動作と結果が異なる場合があるので注意が必要です.例えば,

real a(10) do i = 1, 10

a(i) = i enddo

a(2:10) = a(1:9) ! この配列計算式は単純なdo文で置き換えられない

print *,(a(i),i=2,10)

というプログラムを考えます.この中の配列計算式a(2:10)=a(1:9)do文にすると,

do i = 1, 9 a(i+1) = a(i) enddo

と置き換えられそうですが,実際にやってみるとprint文の出力結果は異なります.配列計算式の場合 は1から9までの異なる数字が出力されるのに対し,このdoループで置き換えると全て1が出力され ます.

これは,配列計算式がdoループのように1要素ずつ計算と代入を繰り返すのではなく,まず右辺の配 列要素計算を全て行って結果を補助配列に保存しておき,その後で保存した補助配列から左辺の配列へ の代入を行うからです.このため,配列代入機能を利用すると,次のように配列要素の順番を逆転させ るのも簡単です.

a(1:10) = a(10:1:-1)

これと同じ動作をするプログラムを1回のdoループで書くのは難しいです.この代入機能は,配列計算 式を使う利点の一つです35

部分配列は要素が等間隔に並んでいますが,整数の1次元配列を使って要素指定をすれば,任意の順 番で指定した配列を作ることができます.例えば,次のような指定ができます.

real a(10) integer m(3),i do i = 1, 10

a(i) = i enddo

m(1) = 7; m(2) = 2; m(3) = 5 print *,a(m)

最後の出力結果は,7.0 2.0 5.0となります.すなわち,a(m)とは,(a(m(1)), a(m(2)) a(m(3))) という要素数3の配列のことです.すなわち,整数配列で要素指定をすると,要素指定配列の要素数を 持つ配列になります.a(m(2:3))のように部分配列を使って要素指定をしたり,6.4節の配列構成子を 使って要素指定をすることもできます.

ドキュメント内 Fortran (2015 ) (ページ 98-101)