IT pass HikiWiki - [itbase2019]Fortran 実習 配列 Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

= 配列

同じデータ型の値を複数まとめて一つの変数名で扱うための仕組みが「配列」です.
配列を使ってみましょう.

下のようなプログラムを vector.f90 というファイル名で作成しましょう.

  program vector

    implicit none

    real :: dotprod
    real :: vectorA(3)                ! 要素数 3 の実数型変数配列 (ベクトル A)

    integer, parameter :: nn = 3      ! 要素数を定数で定義
    real               :: vectorB(nn) ! 要素数 nn(=3) の実数型変数配列 (ベクトル B)

    vectorA(1) =  1.1                    ! 配列への値の代入
    vectorA(2) = -2.2
    vectorA(3) =  3.3
    vectorB(1) = -1.3                   ! 配列への値の代入
    vectorB(2) = -2.5
    vectorB(3) =  0.7

    dotprod = vectorA(1) * vectorB(1) &  ! ベクトル A, B の内積の計算
            + vectorA(2) * vectorB(2) &  ! 行の最後に & を付けると次の行に続く
            + vectorA(3) * vectorB(3)    ! "=" と "+" の位置を合わせる必要はない

    print *, "(", vectorA(1), ",", vectorA(2), ",", vectorA(3), ")"
    print *, "(", vectorB(1), ",", vectorB(2), ",", vectorB(3), ")"
    print *, "Dot product = ", dotprod

    vectorB = vectorA        ! 配列要素すべての代入
                             ! ただし, 要素数が同じ配列同士でなければならない

    print *, vectorB         ! 配列の要素すべての出力

  end program vector

このプログラムは, 1 次元配列をベクトルに見立てて,
二つのベクトル A と B を用意し, それらの内積を
計算しています.

コンパイルして実行してみましょう.

  $ gfortran -o vector vector.f90               <- コンパイル
  $ ./vector                                   <- 実行
   (   1.10000002     ,  -2.20000005     ,   3.29999995     )
   (  -1.29999995     ,  -2.50000000     ,  0.699999988     )
   Dot product =    6.38000011
     1.10000002      -2.20000005       3.29999995

プログラムの内容のいくつかの部分を説明しておきます.

上のプログラムでは, 配列をまず

    real :: vectorA(3)

    <データ型> :: <変数名> ( <要素数> )

として宣言されています.
この時, 配列の添え字は 1, 2, 3 となります.

しかし, より一般的には下のように宣言することができます.

    <データ型> :: <変数名> ( <開始添え字> : <終了添え字> )

具体的には, 例えば,

    real :: vectorA(11:13)

と宣言することができ, この時の配列の添え字は, 11, 12, 13 と
なります. vectorA(11:13) と宣言された配列は, vectorA(3) と宣言された
配列と, 要素数が 3 の意味では同じものですが, 添え字の数字が違うことで
わかりやすいプログラムにすることもできるでしょう.
なお, 添え字には負またはゼロを使うこともできます.


また, 上のプログラムの例では,

    integer, parameter :: nn = 3
    real               :: vectorB(nn)

といったように, 変数 nn を使った配列の宣言も示しています.
このように変数を要素数に用いると, 要素数を変更したい際に,
プログラムの変更箇所が少なくて済み大変便利です.

ただし, 変数を要素数に使った並列の宣言のためには,
要素数の変数 (上の nn) は「定数」でなければなりません.
つまり, parameter 属性を付けた変数のみが要素数として受け
入れられます.

=== 練習問題

上の例のプログラム vector.f90 を変更して, vectorA と vectorB で与えられる
ベクトルの外積を計算するプログラムを作りなさい.

ヒントと答え:
* 結果を保持するための配列, 例えば vectorC(3), を用意する
  * 外積の結果はベクトルです
* 外積を計算する
* 答え

   Cross product = (   6.71000004     ,  -5.05999994     ,  -5.60999966     )


== 多次元配列

詳しくは説明しませんが, 下のプログラムのように,
2 次元以上の多次元配列を使うこともできます.

  program matrix2d

    implicit none

    integer, parameter :: mm = 2, nn = 3   ! 要素数を定数で定義
    real               :: matrix(mm,nn)    ! 要素数 mm x nn の実数型変数配列

    matrix(1,1) = 1.1                    ! 配列への値の代入
    matrix(1,2) = 1.2
    matrix(1,3) = 1.3
    matrix(2,1) = 2.1
    matrix(2,2) = 2.2
    matrix(2,3) = 2.3

    print *, matrix                  ! 配列の要素すべての出力
    print *, matrix(1,3)             ! 要素一つの出力

  end program matrix2d

多次元の数値データを扱うときには便利です.
(例えば行列. 上のプログラムでは 2 x 3 の行列を表すことができます.)


== 補足 1

配列の各要素に値を代入するためには, 添え字を使って要素を指定し, = (イコール) によって値を代入しなければいけません.
しかし, Fortran では, 添え字を付けずに配列に値を代入することもできます.

例えば, 上のプログラム matrix2d を下のように変えて実行してみましょう.
matrix2d からの変更点には, 「追加部分」のコメントが付いていることに注意しましょう.

  program matrix2d

    implicit none

    integer, parameter :: mm = 2, nn = 3   ! 要素数を定数で定義
    real               :: matrix(mm,nn)    ! 要素数 mm x nn の実数型変数配列

    !---追加部分 1 ここから---
    real               :: matrix2(mm,nn)   ! 新しい配列
    real               :: matrix3(mm,nn)   ! 新しい配列
    !---追加部分 1 ここまで---

    matrix(1,1) = 1.1                    ! 配列への値の代入
    matrix(1,2) = 1.2
    matrix(1,3) = 1.3
    matrix(2,1) = 2.1
    matrix(2,2) = 2.2
    matrix(2,3) = 2.3

    print *, matrix                  ! 配列の要素すべての出力
    print *, matrix(1,3)             ! 要素一つの出力


    !---追加部分 2 ここから---
    matrix2 = -10.0                  ! 新しい配列に -10 を代入
    matrix3 = matrix                 ! 新しい配列に matrix の値を代入
    print *, matrix2                 ! 配列の要素すべての出力
    print *, matrix3                 ! 配列の要素すべての出力
    !---追加部分 2 ここまで---


  end program matrix2d

上の例では, matrix2 に -10 を代入し, matrix3 に matrix の値を代入しています.

    matrix2 = -10.0

と書くことで, matrix2 の 2 × 3 = 6 個の要素すべてに -10 が代入されていることに注意しましょう. 添え字を使って配列の要素を指定しない場合には配列のすべての値が同じ値になります.

    matrix3 = matrix

と書くことで, matrix の各要素の値が, 要素の場所を変えずに matrix3 に代入されていることに注意しましょう.
ただし, 上のプログラムでは, matrix も matrix3 も 2 × 3 の要素を持った配列ですが, 異なる大きさを持った配列同士を代入すると間違いが起こりますので注意しましょう.


== 補足 2

ここまでは, 配列の宣言として下のような方法,

  real :: Array(10,10,10)

あるいは,

  integer, parameter :: nx = 10, ny = 10, nz = 10
  real :: Array(nx,ny,nz)

を説明してきました.

しかし, 配列の宣言方法は他にもあります.
例えば, 上の宣言文は, dimension 属性を指定して下のように書くこともできます:

  real, dimension(10,10,10) :: Array

あるいは,

  integer, parameter :: nx = 10, ny = 10, nz = 10
  real, dimension(nx,ny,nz) :: Array

です.

このように dimension 属性を指定した書き方をするプログラムもたくさん存在します.
このような方法があることも頭に入れておくとよいでしょう.