例題6 配列と繰り返し、書式仕様

次のプログラムを作成する。
 実数値を10個読み込んで平均値を計算し、各実数値の平均からのずれを求めて出力する。

 この例題では、10個のデータを読み込んで平均を求めてから、元のデータについてそれぞれ平均からのずれ(差)を求めなければなりません。そのため、データを読み込みながら平均と差を計算することはできないので、あらかじめ10個のデータを読み込んで変数に格納しておかなければなりません。また10個のデータにそれぞれ10個の変数名を付けたのではプログラムが長くなってしまいます。このようなデータを扱うには配列を使用すると便利です。

 例題6のフローチャートとプログラムの例を示します。

概要

プログラム
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
c Example 6     配列と繰り返し、書式仕様
c  機械工学科 1年  xxxxxxx  my name
c         Filename = reidai06.f
      real a(20), s(20)
      n=10
      write(*,*) ' 実数を10個入力する'
      read(*,*) (a(i),i=1,n)
c   10個の実数の平均を求める
      asum=0.0
      do 1010 i=1,n
        asum=asum+a(i)
 1010 continue
      av=asum/real(n)
      write(*,601) ' 平均 ', av
c  平均との差を求める
      write(*,602) '実数値','平均との差'
      do 1020 i=1,n
        s(i)=a(i)-av
        write(*,603) a(i),s(i)
 1020 continue
      stop
  601 format(3x,a6,f5.1)
  602 format(3x,a6,3x,a10)
  603 format(3x,f6.1,3x,f10.1)
      end


 例題6のプログラム例について説明します。

4行目       real a(20), s(20)

は型宣言文で、寸法が 1から 20 の実数型の配列 a と s を定義しています。

5行目       n=10

 データ数の10を変数 n に入れておきます。変数 n を使用しないでプログラム中に直接 10 と記述しても構いませんが、データ数が異なる場合にも応用できるように変数にしておく方がよいでしょう。

 データを読み込む部分は

6行目       write(*,*) ' 実数を10個入力する'
7行目      read(*,*) (a(i),i=1,n)

です。read文では、配列 a の1番目から n 番目の要素( a(1)からa(n) )にデータを読み込みます。 (a(i), i=1,n ) do形並びといいます。

 次に、平均を求めるためにまず合計を計算します。

9行目         asum=0.0
10行目       do  1010  i=1, n
11行目         asum=asum+a(i)
12行目  1010 continue

 9行目から12行目が合計を求める部分です。合計は、a(1)+a(2)+a(3)+・・・+a(n) ですが、n の値が大きくなると、この式では記述しきれなくなります。そこで次のように考えます。

   asum=0.0         asumの初期値をゼロとしておく
   asum=asum+a(1)  i=1の時  asum=0.0+a(1)           右辺のasumの値はゼロ
   asum=asum+a(2)  i=2の時  asum=a(1)+a(2)          右辺のasumの値はa(1)
   asum=asum+a(3)  i=3の時  asum=a(1)+a(2)+a(3)     右辺のasumの値はa(1)+a(2)
       :
   asum=asum+a(n)  i=nの時  asum=a(1)+・・・+a(n)   右辺のasumの値はa(1)+・・・+a(n-1)

 これを do文を使用して9行目から12行目までのように記述します。doは、do文の次の文から、do文で指定された文番号を持つ文(端末文)までの範囲を do変数(ここでは i)の指示にしたがって繰り返します。
 10行目のdo文では、繰り返しの範囲を示す文(端末文)の文番号(ここでは 1010)と、do変数 i に doの制御(ここでは1から順に n まで繰り返すこと)を記述しています。この例では、doの端末文(行番号1010を持つ文)は12行目の 1010 continueですから、11行目の文 asum=asum+a(i)を do変数 i について1から n まで繰り返すことになります。

 平均との差を求めて出力する部分は13行目から14行目です。

13行目       av=asum/real(n)
14行目       write(*,601) ' 平均 ', av

 13行目では、合計 asum の値を、個数 n を実数型の値に変換してから割り算します。整数値を実数値に変換するにはreal関数を用います。real関数はFortranが用意している関数(組込み関数)です。14行目のwrite文で、平均値 av を出力します。

 平均との差を求めて出力する部分は16行目から20行目です。

16行目       write(*,602) '実数値','平均との差'
17行目       do 1020 i=1,n
18行目         s(i)=a(i)-av
19行目         write(*,603) a(i),s(i)
20行目  1020 continue

 16行目のwrite文で、あらかじめ文字列 「実数値」と「平均との差」を出力しています。17行目のdo文で、20行目の文番号1020のcontinue文までを do変数 i について1から n まで繰り返します。
 18行目ではi番目のデータa(i)と平均 av との差を計算し、差 s(i) に代入しています。この例では計算しながら出力していますので差 s を配列にする必要はないのですが、この後、差を用いた処理を行う場合には、配列に格納しておかねばなりません。
 19行目では、データ(配列要素a(i))と差(配列要素s(i))を出力しています。

 この例題では、write文に書式仕様を用いています。書式仕様に関連する部分を抜き出したのが次の行です。

14行目       write(*,601) ' 平均 ', av
    :
16行目       write(*,602) '実数値','平均との差'
17行目       do 1020 i=1,n
    :
19行目         write(*,603) a(i),s(i)
20行目  1020 continue
    :
22行目   601 format(3x,a6,f5.1)
23行目   602 format(3x,a6,3x,a10)
24行目   603 format(3x,f6.1,3x,f10.1)

 14行目のwrite文は平均を出力しています。このwrite文の並びは文字列「 平均 」と変数 av です。これを文番号601 の format文の書式仕様にしたがって出力します。まず 3x により3桁分移動します。次に文字列「 平均 」を a6(6桁の右詰)で、変数 av の値を f5.1(5桁の幅を取って小数点以下1桁までを右詰)で出力します。
 16行目のwrite文の並びは文字列「実数値」と「平均との差」です。これを文番号602 の format文の書式仕様にしたがって出力します。まず 3x で、3桁分移動します。次に文字列「実数値」を a6(6桁の右詰)で、3桁分移動してから、文字列「平均との差」を a10(10桁の右詰)で出力します。
 19行目のwrite文はdo文のループの中にありますので n 回(ここでは10回)実行されます。このwrite文の並びは配列要素 a(i) と s(i) です。これを文番号603 の format文の書式仕様にしたがって出力します。まず 3x で、3桁分移動します。次に a(i) の値を f6.1(6桁の幅を取って小数点以下1桁までを右詰)で、3桁分移動してから、 s(i) の値を f10.1(10桁の幅を取って小数点以下1桁までを右詰)で出力します。

 例題6の出力結果は次のようになります。

入力した実数値は「1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0」です。

    平均   5.5
   実数値   平均との差
      1.0         -4.5
      2.0         -3.5
      3.0         -2.5
      4.0         -1.5
      5.0         -0.5
      6.0          0.5
      7.0          1.5
      8.0          2.5
      9.0          3.5
     10.0          4.5


Fortranの文法参照