Comments
Description
Transcript
FORTRAN - 総合情報センター
プログラミング言語 FORTRAN 東海大学総合情報センター 第3版 第1章 マスターへの道のり 1.1 FORTRAN のプログラム 1.2 FORTRAN プログラムの例 1.3 基本的な命令 …… …… …… 1 2 4 …… …… …… …… …… …… 6 8 9 9 12 13 …… …… …… 15 17 18 …… 20 …… …… 23 24 …… …… …… …… …… 26 26 29 30 31 …… …… …… 34 35 35 …… …… …… …… …… 36 36 37 37 37 …… …… …… …… …… …… 38 38 38 39 41 42 第2章 型と式 2.1 2.2 2.3 2.4 2.5 2.6 整数型と実数型 倍精度実数型 複素数型 文字型と文字式 論理型と論理式 演算子の優先順位 第3章 配列 3.1 配列要素の参照 3.2 添字の上限値、下限値 3.3 配列の次元数 第4章 補助入出力 −ファイルの利用− 4.1 ファイルのオープン 第5章 書式付きの入出力 5.1 出力 FORMAT 5.2 入力 FORMAT 第6章 副プログラム 6.1 6.2 6.3 6.4 6.5 主プログラムと副プログラム 関数副プログラム サブルーチン副プログラム COMMON文 整合配列 第7章 便利な利用方法 7.1 定数の便利な利用法 −PARAMETER 文− 7.2 変数の便利な利用法 −DATA 文− 7.3 関数の便利な利用法 −文関数定義− 第8章 演習問題 8.1 8.2 8.3 8.4 8.5 Simpson の公式による数値積分 Gauss-Jordan 法(掃き出し法)による連立方程式の解法 素数の判定 最大公約数と最小公倍数を求める 自作sin関数(Maclaurin 展開とシステムsin関数の比較) 第9章 付録 9.1 9.2 9.3 9.4 9.5 9.6 利用できる文字 プログラムの構成 演算子 命令文の分類 組み込み関数表 アプリケーションサーバ(bosei)上での実習 第1章 マスターへの道のり 1950 年代中ごろに IBM 社によって開発されて以来 FORTRAN は数々の改良を加えられ現 在に至っています。現在では 1980 年代初期に制定された FORTRAN77、1990 年代初めに制 定 さ れ た Fortran90 、 1990 年 後 半に 制定された Fortran95 も利用されています。さらに Fortran2000 の制定の作業が進んでいます。 ここでは、FORTRAN77 の規格に添って解説を行います。 また、このテキストでは文法の一部を抜粋して説明していますので、詳細についてはその他の 文法書などを参照してください。 1.1 FORTRAN のプログラム FORTRAN プログラムには固定書式(形式)と自由書式(形式)の2種類があります。本テキスト では固定書式を採用して例題等を表記しています。なお、固定書式は Fortran95 で(次回改正時 の)廃止予定事項になりました。固定書式で書かれたプログラムは、注釈行(!で注釈行をはじめ る)と継続行(&で継続行をはじめる)の書き方を変更することで自由書式に移行できます。 FORTRAN プログラムは定数、英字名、キーワードおよび特殊記号などから構成され、固定書 式の場合プログラムは以下のように定まった桁位置から書き始めます。 1 桁目 C もしくは*の場合は注釈行と解釈されます。 1 桁目から 5 桁目 文番号を記述します。 文番号は最大 5 桁の数字の列(1∼99999)です。 6 桁目 継続行の指定のために設定されています。この桁が空白、または 0 以外の文字であれば前の行からの継続と見なされます。 7 桁目から 72 桁目 プログラムを記述します。プログラムは定数、英字名、キーワードお よび特殊文字から構成されます。 定数 定まった値(数値、文字)を表すものです。 (例) 100 20.0 5.0E7 'abcdefg' 英字名 変数名、配列名、関数副プログラム名、サブルーチン副プログラム名などがこれに当たります。 これらも名前は英文字(A-Z)で始まる、最大 6 文字の英数字および特殊文字($ _)によって構成さ れる文字列です。 (例) A1 XY IGEN1 DATA キーワード FORTRAN として意味を持つキーワード(例えば READ,WRITE,END などの命令)で英字 名の構成規則に従っています。プログラム中の英字名、キーワードの区別は文脈によって決定さ れます。プログラム中の空白(文字列データの空白は除く)はプログラムに影響を与えません。 1 特殊文字 特殊文字は演算子または定数の一部になる場合や、他の特殊な意味を持つ場合があり、その 解釈は文脈によって決定されます。 1.2 FORTRAN プログラムの例 例題 「体格指数(BMI)法を使用した肥満度の判定」 BMI 値は次のようにして求めます。 BMI=体重(kg)÷身長(m)÷身長(m) BMI 値と肥満の関係は右の表のようになります。 BMI 値の範囲 20>BMI 20≦BMI<24 24≦BMI<26.5 26.5≦BMI 診断 やせぎみ 正常 肥満ぎみ 肥満 (プログラム例) PROGRAM BMI REAL H,W,BMI 100 CONTINUE READ(*,*,END=999) H,W BMI=W/H/H IF(BMI.LT.20.0) THEN WRITE(*,*) 'yasegimi BMI=',BMI ELSE IF (BMI.GE.20.0 .AND. BMI.LT.24.0) THEN WRITE(*,*) 'seijou BMI=',BMI ELSE IF (BMI.GE.24.0 .AND. BMI.LT.26.5) THEN WRITE(*,*) 'yaya himan BMI=',BMI ELSE WRITE(*,*) 'himan BMI=',BMI ENDIF 身長,体重 の読込 GO TO 100 999 はじめ CONTINUE BMI<20 STOP データ 終了 はい おわり やせぎみ いいえ END 20≦BMI<24 はい 正常 いいえ 24≦BMI<26.5 (入力例) はい やや肥満 いいえ 肥満 1.7 68 CTRL + D (出力例) seijou BMI= 23.5294 注)入力例の CTRL + D は CTRL キーを押しながら D のキーを押すことを意味します。 この操作はデータの入力が終了したこと示します。 2 例題 「2 のべき乗」 20 から 210 までの値を計算するプログラムを作成しなさい。 (プログラム例) はじめ PROGRAM PW2 INTEGER I,J DO I=0,10 DO 100 I=0,10 2のベキ乗の計算 J=2**I WRITE(*,*) 100 I,J 計算結果の印刷 CONTINUE STOP END おわり (出力例) 0 1 1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024 3 1.3 基本的な命令 以下に FORTRAN の基本的な命令についての簡単な解説を行います。 READ 文 入力装置から書式指定に従って入力並びにデータを読み込みます。 READ(装置識別子,書式識別子, [END=文番号]) 入力並び 装置識別子 * :システム標準入力装置 番号:装置番号 文字変数:入力データが納められている文字変数 書式識別子 * :自由書式 文番号:FORMAT 文を示す文番号 文字変数、定数:書式の文字列が格納されている文字変数あるいは文字定数 WRITE 文 出力装置へ書式に従って出力並びを出力します。 WRITE(装置識別子,書式識別子) 出力並び 装置識別子 * :システム標準出力装置 番号:出力装置番号 文字変数:出力データが納められる文字変数 書式識別子 * :自由書式 文番号:FORMAT 文を示す文番号 文字変数、定数:書式の文字列が格納されている文字変数あるいは文字定数 GOTO 文 プログラムの実行を文番号で指定した文へ移す。 GOTO 文番号 文番号:制御を移す文番号 DO 文 指定された範囲を、指定された回数繰り返し実行します。 DO 文番号 変数=式 1,式 2,式 3 文番号 :繰り返しの範囲を示す端末文の文番号 変数 :繰り返し回数を制御する制御変数 式1 :初期値 式2 :終値 式3 :増分(1 の場合には省略可) 4 CONTINUE 文 GOTO 文の制御を移す先、あるいは DO 文の端末文として使用されます。元は何もしないとい う意味の命令です。 文番号 CONTINUE ブロック IF 文 条件分岐を行います。 IF(条件式 1)THEN 命令 A [ ELSE IF(条件式 2) THEN 命令 B ] [ ELSE 命令 C ] ENDIF 条件式 1,2:条件式が真の場合 THEN 以降の命令を実行します。 命令 A または B を実行したあとは ENDIF 文の次に制御を移します。 命令 C:すべての条件式に対して偽である場合 ELSE 以降の命令(命令 C) を実行します。 5 第2章 型と式 FORTRAN で扱うデータには次の 6 つの型があります。 (1) 整数型 (2) 実数型 (3) 倍精度実数型 (4) 複素数型 (5) 文字型 (6) 論理型 定数や名前(変数名や配列名など)は1つの型を持ちます。この章ではこれらのデータ型につ いて定数と名前、式について説明します。 2.1 整数型と実数型 整数型と実数型ではコンピュータ内部での表現方法が異なります。型の違いによって演算結 果に思わぬ違いが発生することがあります。算術演算を行う場合は、扱うデータの型を十分に意 識するようにしてください。整数型の定数と実数型の定数は次のように表現します。 ・整数型の定数は、正または負を表す符号とそれに続く空でない数字の列で表します。 整定数では-2147483648∼2147483647 まで表現でき、正の符号は省略できます。 10 -123 ・ 実数型の定数は、4バイトで数値表現を行います。そのため、表現可能な数値の範囲は、正の 最大値で 3.4028×1038、正の最小値で 1.4012×10-45です。 実数型の定数は次の3つの表現があります。 (1) 小数点を持った基本実定数 12.5 0. -.45 (2) 基本定数とそれに続く実指数部 6.3E2 (6.3 × 102) 2.5E-3 (2.5 × 10-3) (3) 整数とそれに続く実指数部 (8 × 106) 8E6 名前(変数名など)の型は、型宣言文によって宣言します。 ・整数型の名前は、型宣言文である INTEGER 文で宣言します。 INTEGER GOUKEI , TENSU ・実数型の名前は、 REAL 文で宣言します。 REAL KADAI , JIKAN 6 型宣言文で宣言されていない名前は、名前の 1 文字目が、I,J,K,L,M,N で始まるものは整数 型、それ以外は実数型とみなされます。これを、「暗黙の型宣言」といいます。しかし、プログラム の見やすさを考えると、型宣言文で宣言することを推奨します。 算術演算を行った結果の型は、演算を行うデータの型によって決まります。つまり、整数型同 士の演算は結果も整数型となり、実数型同士の演算は結果も実数型となります。特に整数型同士 の除算の場合は、小数点以下が切り捨てられてしまうことに注意してください。 また、代入の時も代入する変数の型に合わせて型の変換が行われます。整数型の変数名に 実数値を代入すると、小数点以下が切り捨てられてしまいます。 (例) 変数名と定数の型に注意してください PROGRAM REI1 INTEGER SEISU1 , SEISU2 REAL JISU1 , JISU2 SEISU1 = 3 / 2 JISU1 = 3 / 2 SEISU2 = 3.0 / 2.0 JISU2 = 3.0 / 2.0 WRITE(*,*) SEISU1 , JISU1 , SEISU2 , JISU2 STOP END (出力例) 1 1.00000 1 1.50000 型が違うデータを用いて演算すると型の変換が行われ、結果は次の表のようになります。 整数型 実数型 倍精度実数型 複素数型 整数型 整数型 実数型 倍精度実数型 複素数型 実数型 実数型 実数型 倍精度実数型 複素数型 倍精度実数型 複素数型 倍精度実数型 複素数型 倍精度実数型 複素数型 倍精度実数型 複素数型 複素数型 複素数型 例題 「型混合の計算」 あるクラスの身長を調べたデータがある。身長のデータは小数点以下1桁まで入っているもの とする。このデータを使ってクラスの平均身長を求めるプログラムを作りなさい。 ただし、平均値が入る変数のみを整数型として宣言し、実数の計算結果が代入時に整数に変 換されることを確認しなさい。 7 (プログラム例) PROGRAM はじめ SINTYO REAL SINTYO,GOKEI,NINZU 変数の初期化 INTEGER HEIKIN GOKEI = 0 身長を入力 データ終了 NINZU = 0 100 合計,人数の計算 READ(*,*,END=200) SINTYO GOKEI = GOKEI + SINTYO NINZU = NINZU + 1 平均の計算 GOTO 100 200 HEIKIN = GOKEI / NINZU WRITE(*,*) 結果の出力 GOKEI,NINZU,HEIKIN STOP おわり END (入力例) 174.5 160.0 182.5 167.5 172.0 158.0 CTRL + D (出力例) 1014.50 6.00000 169 2.2 倍精度実数型 倍精度実数型は、コンピュータ内での数値表現を実数型(4 バイト)の倍(8 バイト)使うことによ って、より正確に表現するものです。表現可能な数値の範囲は、正の最大値で 1.7976×10308、 正の最小値で 4.9406×10-324です。 倍精度実数型の定数は次の2つの表現があります。 (1)基本実定数とそれに続く倍精度指数部 6.3D2 6.3 × 102 2.5D-3 2.5 × 10-3 (2)整定数とそれに続く倍精度指数部 8 × 106 8D6 倍精度実数型の名前は REAL*8 文で宣言します。 REAL*8 INDATA 8 2.3 複素数型 複素数型は複素数値を実部と虚部の対で表します。 複素数型の定数は、実部を表す定数、虚部を表す定数の順にコンマで区切り、全体をカッコ でくくります。 (7.8 , 1.26) 7.8 + 1.26 − 1 7.8 + 1.26i (2E-5 , 7.2) 2×10-5 + 7.2 − 1 2 × 10-5 + 7.2i 複素数型の名前は COMPLEX 文で宣言します。 COMPLEX FUKUSO , COMP 2.4 文字型と文字式 文字型のデータは英数字・記号を文字として扱うもので、それぞれの文字は対応する文字コ ードによって記憶されています。文字型のデータは、たとえ数字のみのデータであっても算術演 算を行うことはできません。 文字型の定数は、文字列をアポストロフィでくくったものです。データの中にアポストロフィを入 れる場合は、連続する2つのアポストロフィで表します。 'TOKAI UNIV.' TOKAI UNIV. 'IT''S OK' IT'S OK 文字型の名前は、 CHARACTER 文で宣言します。 CHARACTER 文には長さの指定が必要です。例えば 8 文字までの文字列を代入するため の変数名 NAMAE を宣言する場合は次のようにします。 CHARACTER*8 NAMAE また、長さが異なる複数の変数名を宣言する場合は、変数名の後に長さを指定することもでき ます。 CHARACTER NAMAE*8 , JYUSYO*20 文字型のデータは、文字演算子 // を使った文字列の連結が行えます。 JYUSYO = 'KANAGAWA' // 'HIRATUKA' 9 例題 「文字列の結合」 2人分の姓と名を入力し、姓と名の組み合わせを替えた2つの名前を作って印刷するプログラ ムを作りなさい。 (プログラム例) PROGRAM NAME CHARACTER*10 SEI1,SEI2,MEI1,MEI2 CHARACTER*20 NAMAE1,NAMAE2 READ(*,*) SEI1,MEI1 はじめ 姓と名を 2 組入力 READ(*,*) SEI2,MEI2 組み合わせを替える NAMAE1=SEI1 // MEI2 NAMAE2=SEI2 // MEI1 結果を出力 WRITE(*,*) NAMAE1 WRITE(*,*) NAMAE2 おわり STOP END (入力例) 'TANAKA' , 'KAZUO' 'ISHIDA' , 'TARO' (出力例) TANAKA TARO ISHIDA KAZUO 10 例題 「乱数1(発生)」 次の方法で 0.0 より大きく 1.0 未満の乱数を発生させ、乱数を 20 個印刷するプログラムを作成 しなさい。 はじめ (乱数の発生方法) 1.0 未満の適当な数を素数倍して小数点以下の数を乱数とす る。最初に 1.0 未満の数と素数を入力して乱数を 1 個発生させ、 適当な数 a と 素数 b を入力 2 個目以降は 1 つ前の乱数を使って計算する。 20 回繰り返す (プログラム例) PROGRAM RANSU REAL A,B,C INTEGER I READ(*,*) A,B DO 100 I=1,20 C = A * B A = C – INT(C) WRITE(*,*) A 100 CONTINUE STOP END a*b を求める 小数点以下を乱数とする 求めた数を a とする 乱数を印刷する おわり (入力例) 0.423 12341.0 (出力例) 0.243164 0.887695 4.78516E-02 0.536133 0.415039 0.997070 0.844727 0.770508 0.836914 0.356445 0.891602 0.254883 0.508789 0.965820 0.188477 0.989258 0.430664 0.825195 0.735352 0.973633 11 2.5 論理型と論理式 論理型データは真か偽のどちらかの値を持ちます。論理型の定数は、真の値を表 す、 .TRUE. と、偽の値を表す .FALSE. の 2 つの値があります。 .TRUE. 真 .FALSE. 偽 論理型の名前は、 LOGICAL 文で宣言します。 LOGICAL HANTEI 論理型データの演算は論理式によって表します。論理式は論理型のデータや関係式、論理 演算子の組み合わせによって表現します。 (関係式) 関係式は 2 つの値を関係演算子によって比較したもので、真か偽の論理型の結果を持ちま す。 (関係式の例) A .LT. B A が B より小さければ真、そうでなければ偽 M .GE. N M が N より大きいもしくは等しければ真、 そうでなければ偽 (論理演算子) 論理演算子は論理型データに対する演算を行い、論理積や論理和などを求めるものです。 演 算 子 意 味 .NOT. 否定 .AND. 論理積 .OR. 論理和 論理等価 .EQV. 論理非等価 .NEQV. 関係式と組み合わせることで、より複雑な条件の記述ができるようになります。 (関係式と論理演算子) M .GT. 10 .OR. M .EQ. 0 M が 10 より大きいかまたは M が 0 なら真 12 (例) N が 0 以下の時と N が 100 以上の時に偽となり、それ以外の場合に真となるような論理式を考 えてみます。N が 0 以下または N が 100 以上の場合というのは、 N.LE.0 .OR. N.GE.100 と表現できますので、この時を偽とするには否定を使って、 .NOT.(N.LE.0.OR.N.GE.100) となります。なお、 N.GT.0.AND.N.LT.100 0 100 0 100 0 100 としても同じ事ですが、否定を使った方が問題を忠実に表現できる場合もあります。 2.6 演算子の優先順位 式の解釈規則によって、次のように優先順位が定められています。 1. かっこの使用 2. 算術演算子 2.1 ** 2.2 * および / 2.3 + および – 3. 文字演算子 4. 関係演算子 5. 論理演算子 5.1 .NOT. 5.2 .AND. 5.3 .OR. 5.4 .EQV. または .NEQV. 13 例題 「乱数2(分布判定)」 前の例題で作った乱数を発生するプログラムを使い、少数点以下 1 桁目の値を使って整数 型の乱数を作り、2 または 5 となる確率を求めなさい。ただし、乱数は 100 個発生させて求めな さい。 (プログラム例) PROGRAM REAL はじめ RANSU2 適当な数 a と 素数 b を入力 A,B,C INTEGER I,J,RND J = 0 100 回繰り返す READ(*,*) A,B a*b を求める DO 100 I=1,100 C = A * B 小数点以下を a とする A = C - INT(C) 小数点以下 1 桁目を 乱数とする RND = INT(A*10) IF(RND.EQ.2.OR.RND.EQ.5)THEN J=J+1 2 または 5 か? ENDIF 100 いいえ CONTINUE WRITE(*,*) J,J/100. STOP 数を出力 END おわり (入力例) 0.423 12341.0 (出力例) 23 0.230000 14 はい 数をカウント 第3章 配列 INTEGER や REAL の型宣言文によって宣言された変数には1つの記憶領域が割り当てられ ます。配列として宣言した場合は、指定した数だけの連続した記憶領域を割り当てることができま す。配列の宣言は DIMENSION 文または型宣言文(INTEGER,REAL,CHARACTER など)で行 えます。ここで、配列の大きさは寸法宣言子によって指定します。寸法宣言子は整定数で指定し ます。 DIMENSION 配列名 1(寸法宣言子 1),……,配列名 n(寸法宣言子 n) 型宣言文 配列名 1(寸法宣言子 1),……,配列名 n(寸法宣言子 n) (例) 整数型で大きさ 20 の配列を宣言するためには以下のようにします。 型宣言文にて行う場合 DIMENSION文と型宣言文を併用する場合 INTEGER A(20) INTEGER A DIMENSION A(20) この例では、配列 A は A(1)∼A(20)の 20 個の要素を持ちます。配列の要素部分を指定する ()で囲まれた数字を添字と呼びます。 配列 A の添字と記憶領域との関係は次のようになります。 配列 A 1 番目 2 番目 11 番目 ……… ……… の要素 の要素 の要素 A(1) A(2) ……… A(11) ……… 20 番目 の要素 A(20) 3.1 配列要素の参照 配列要素を参照する場合の添字は次のようになります。 配列名(添え字式) 添え字式の値は整数でなくてはいけません。添字式は定数、変数、算術式で記述できます。 例題 「ソート1」 N 個の数字を配列として入力し、交換法のアルゴリズムを用いて降順(大きい順)に並べ替えを 行うプログラムを作成しなさい。 (交換法のアルゴリズム) (1) 1番目の数と2番目∼N番目までの数との大小を比較します。 (2) 2番目∼N番目までに1番目より値の大きな数があった場合はその度に1番目と交換し ます。 (3) 2番目と3番目以降の数とを比較し、3番目以降に大きいものがあれば同様に交換を行 います。 (4) これをN−1番目の数まで行います。 15 A(1) A(2) A(3) A(4) A(5) 20 25 23 14 28 元の配列→A(1)と A(2)以下を順に比較 20 25 23 14 28 A(1)<A(2) 25 20 23 14 28 A(1)と A(2)の交換 25 20 23 14 28 A(3),A(4)は交換なし 25 20 23 14 28 A(1)<A(5) 28 20 23 14 25 A(1)と A(5)の交換→A(1)最大 28 20 23 14 25 A(2)と A(3)以下を順に比較→A(2)<A(3) 28 23 20 14 25 A(2)と A(3)の交換 28 23 20 14 25 A(4)は交換なし 28 23 20 14 25 A(2)<A(5) 28 25 20 14 23 A(2)と A(5)の交換→A(2)に 2 番目に大きな値 28 25 20 14 23 A(3)と A(4)以下を順に比較→A(4)は交換なし 28 25 20 14 23 A(3)<A(5) 28 25 23 14 20 A(3)と A(5)の交換→A(3)に 3 番目に大きな値 28 25 20 14 20 A(4)と A(5)を比較→A(4)<A(5) 28 25 23 20 14 A(4)と A(5)の交換→ソート終了 28 25 23 20 14 結果の配列 比較回数は Σ(N-1)-1 回 (プログラム例) 16 PROGRAM SORT1 INTEGER NUM(100),N,NUM2,I,J はじめ READ(*,*) N デー タ数 N,値 NUM を入 力 READ(*,*) (NUM(I),I=1,N) DO 100 I=1,N-1 DO I=1,N-1 DO 100 J=I+1,N DO J=I+1,N IF(NUM(J).GT.NUM(I)) THEN NUM2=NUM(I) NUM(J)>NUM(I) NUM(I)= NUM(J) いいえ はい NUM(J)←→NUM(I) NUM(J)= NUM2 ENDIF 100 CONTINUE WRITE(*,*) (NUM(I),I=1,N) NUM の 出力 STOP おわり END (入力例) 5 2 3 5 0 8 (出力例) 8 5 3 2 0 READ(*,*) (NUM(I),I=1,N)という命令は READ(*,*) NUM(1), NUM(2), …, NUM(N) と同じとして解釈、実行されます。 3.2 添字の上限値,下限値 配列の要素を指定する添字は通常1から始まります。この添字を任意の範囲の数値で使用す るためには、配列を宣言する時に寸法宣言子を配列の大きさでなく、添字の下限値と上限値を 「:」で区切って指定します。 DIMENSION 配列名(下限値:上限値),……,配列名 n(下限値:上限値) 型宣言文 配列名(下限値:上限値),……,配列名 n(下限値:上限値) (例) サイズ 21 の実数型配列 B を-10∼10 の範囲の添字を使用して参照する場合 REAL B(-10:10) 配列 B の添字と記憶領域との関係は次のようになります 1 番目 2 番目 の要素 の要素 B(-10) B(-9) ……… 11 番目 の要素 B(0) (例) 17 ……… 20 番目 21 番目 の要素 の要素 B(9) B(10) 上限値、下限値を使用して配列を宣言し、sin、cos の結果を納める PROGRAM SINTBL REAL S(-180:180),C(-180:180) INTEGER I DO 100 I=-180,180 S(I)=SIN(3.1415926/180.0*I) C(I)=COS(3.1415926/180.0*I) WRITE(*,*) S(I),C(I) 100 CONTINUE STOP END 3.3 配列の次元数 配列の次元は7次元まで宣言できます。1次元以上の配列を宣言する場合は以下のようになり ます。 DIMENSION 配列名(寸法宣言子 1,寸法宣言子 2,…,寸法宣言子 7) 型宣言文 配列名(寸法宣言子 1,寸法宣言子 2,…,寸法宣言子 7) (例) サイズ3×3の2次元実数型配列の宣言は以下のようになります REAL T(3,3) 2次元配列 T の添字と記憶領域との関係は次のようになります 1 番 目 2 番 目 3 番 目 4 番 目 5 番 目 6 番 目 7 番 目 8 番 目 9 番 目 の要素 の要素 の要素 の要素 の要素 の要素 の要素 の要素 の要素 T(1,1) T(2,1) T(3,1) T(1,2) T(2,2) T(3,2) T(1,3) T(2,3) T(3,3) 例題 「行列のかけ算1」 3×3行列のかけ算を行うプログラムを作成しなさい。 (解説) 3×3の行列のかけ算は以下のようになります。 ⎡ a11 ⎢a ⎢ 21 ⎣⎢ a 31 a12 a 22 a 32 a13 ⎤ ⎡ b11 a 23 ⎥ × ⎢b21 ⎥ ⎢ a 33 ⎦⎥ ⎣⎢b31 b12 b22 b32 ⎡ a11 ⋅ b11 + a12 ⋅ b21 + a13 ⋅ b31 = ⎢ a 21 ⋅ b11 + a 22 ⋅ b21 + a 23 ⋅ b31 ⎢ ⎢⎣ a 31 ⋅ b11 + a 32 ⋅ b21 + a 33 ⋅ b31 b13 ⎤ b23 ⎥ ⎥ b33 ⎦⎥ a11 ⋅ b12 + a12 ⋅ b22 + a13 ⋅ b32 a 21 ⋅ b12 + a 22 ⋅ b22 + a 23 ⋅ b32 a 31 ⋅ b12 + a 32 ⋅ b22 + a 33 ⋅ b32 a11 ⋅ b13 + a12 ⋅ b23 + a13 ⋅ b33 ⎤ a 21 ⋅ b13 + a 22 ⋅ b23 + a 23 ⋅ b33 ⎥ ⎥ a 31 ⋅ b13 + a 32 ⋅ b23 + a 33 ⋅ b33 ⎥⎦ a の行列については行の方向へ、b の行列については列の方向に要素を移動させ対応する 要素をかけて足し込む操作を行います。 (プログラム例) 18 PROGRAM MATRIX はじめ REAL A(3,3),B(3,3),C(3,3) INTEGER I,J,K 配列、変数の宣言 READ(*,*) ((A(I,J),J=1,3),I=1,3) READ(*,*) ((B(I,J),J=1,3),I=1,3) DO 100 I=1,3 DO 100 J=1,3 I と J を1から 3 まで繰り返す 総和を入れる配列 C を初期化する C(I,J)=0 DO 100 K=1,3 C(I,J)=C(I,J)+A(I,K)*B(K,J) 100 CONTINUE DO 200 I=1,3 WRITE(*,*) (C(I,J),J=1,3) 200 K を 1 から 3 まで繰り返す A,B の積の総和 を C に代入 CONTINUE STOP END 配列 C を出力 おわり (入力例) 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 行列 a のデータ 行列 b のデータ (出力例) 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000 19 第4章 補助入出力 −ファイルの利用− この章では、プログラム内でファイルからデータを読み込んだり、ファイルに出力する方法につ いて説明します。 プログラム内でのファイル操作が可能になると、大量のデータを必要とするプログラムを実行す る時には、データをあらかじめ用意してあるファイルから読み込むことができます。出力結果をいく つかのファイルに分類して格納することができると結果分析の際に役立ちます。 4.1 ファイルのオープン 操作の対象となるファイルを、OPEN 文を用いて装置と接続します。 OPEN(装置指定子, FILE='ファイル指定子', STATUS='STATUS 指定子') 装置指定子: 通常は「UNIT=外部装置識別子」という形で表されますが、[UNIT=]の部分 は省略することができます。 外部装置識別子: 0 または正の値をもつ、整数式を指定します。OPEN 文の引数には一つの 外部装置識別子が含まれなくてはいけません。5 や 6 など、標準の入出力 にすでに割り当てられている番号もありますので、まだ割り当てられてない 識別子の番号を指定します。 FILE 指定子: 指定した装置と接続するファイルの名前である文字式を指定します。 STATUS 指定子:OLD、NEW、UNKNOWN いずれかを指定します。 OLD 既存のファイルを装置に接続する NEW 新規のファイルを作成して装置に接続する UNKNOWN 既存ファイルは OLD、新規ファイルは NEW で OPEN OPEN 文によって開いたファイルに対し、入出力操作を行う場合には次のように装置指定子を 指定します。 READ(装置指定子,書式指定子) 入力並び WRITE(装置指定子, 書式指定子) 出力並び OPEN 文によって装置に接続されたファイルは操作が終了したら CLOSE 文によってとじます。 CLOSE 文の引数には装置指定子を指定します。 CLOSE(装置指定子) (プログラム例) PROGRAM FLOPEN INTEGER I,J OPEN(20, FILE='INFILE', STATUS='OLD') OPEN(30, FILE='OUTFILE', STATUS='NEW') 100 READ(20,*,END=200) I,J K=I*J WRITE(30,*) I,'*',J,'=',K 20 GOTO 100 200 CLOSE(20) CLOSE(30) STOP END 例題 「ソート2(入出力ファイルの利用)」 前章の例題で扱った、ソートのプログラムを元に以下の通り改良しなさい。 (1) 既存ファイル(tensu.dat)からデータ数、名前、点数を読み込む (2) 点数順にデータをソートし、結果を新規ファイル(kekka.dat)に出力する (3) 交換法のアルゴリズムを理解し、配列の入れ替え回数が少なくなるよう工夫する (プログラム例) PROGRAM SORT2 INTEGER NUM(100),N,MAX,NUM2,I,J CHARACTER NAME(100)*10,NAME2*10 OPEN(UNIT=20,FILE='tensu.dat',STATUS='OLD') OPEN(UNIT=30,FILE='kekka.dat',STATUS='NEW') はじめ READ(20,*) N READ(20,*) (NAME(I),NUM(I),I=1,N) ファイルからデータ数 N, 点数 NUM, 名前 NAME を読込 DO 100 I=1,N-1 MAX=I DO I=1,N-1 DO 200 J=I+1,N MAX ← I IF(NUM(J).GT.NUM(MAX)) THEN DO J=I+1,N MAX=J ENDIF 200 NUM(J)>NUM(I) CONTINUE MAX ← J いいえ NUM2=NUM(MAX) NUM(MAX)=NUM(I) NUM(I)=NUM2 NUM(MAX) ←→ NUM(I) NAME(MAX) ←→ NAME(I) NAME2=NAME(MAX) NAME(MAX)=NAME(I) NAME(I)=NAME2 100 NUM,NAME CONTINUE おわり DO 300 I=1,N WRITE(30,*) 'No.',I,':',NAME(I),NUM(I) 300 CONTINUE CLOSE(20) CLOSE(30) STOP END 21 はい の出力 (入力データ(tensu.dat)例) 10 'T.Yamada',80 'H.Tanaka',65 'Y.Go',91 'R.J.',100 'K.Yoshida',54 'I.Ito',47 'P.Tanimoto',96 'K.Katsuta',87 'S.Kogawara',38 'K.Kotaka',43 (出力データ(kekka.dat)例) No. 1:R.J. 100 No. 2:P.Tanimoto 96 No. 3:Y.Go 91 No. 4:K.Katsuta 87 No. 5:T.Yamada 80 No. 6:H.Tanaka 65 No. 7:K.Yoshida 54 No. 8:I.Ito 47 No. 9:K.Kotaka 43 No. 10:S.Kogawara 38 「ソート2」のプログラム例では、「ソート1」よりも計算ステップが削減できます。 文番号 200 で終了する DO ループに着目すると、NUM や NAME の配列要 素の入れ替えが入っていません。かわりに、最大となる配列の添え字を MAX に 記憶するのです。DO ループ終了後(全ての比較終了後)最大の配列要素に入 れ替える、というわけです。 このように少しの工夫で計算時間が大きく削減できるケースは少なくありませ んので、プログラムを組むときには十分注意を払いましょう。 特に DO ループの中に省略できる命令がないか、IF による無駄な判定はない か、などに着目するとよいでしょう。 22 第5章 書式付きの入出力 FORMAT 文を使うとデータの入出力時にデータ形式の細かい指定が可能となります。 5.1 出力 FORMAT WRITE 文と FORMAT 文を組み合わせることにより、出力形式を細かく指定できます。 FORMAT 文は非実行文ですのでプログラム中であればどこに記述しても構いません。 WRITE(*,文番号) 出力並び 文番号 FORMAT(編集記述子の並び) 紙送り指定 形 式 解 説 ’1H’ または ’ ’ 次の行の先頭から印刷 ’1H0’ または ’0’ 1行おきに印刷 編集記述子 形 式 記 述 子 解 説 整数 Iw 実数 Fw.d 文字 Aw w は文字数 空白 nX n は右に移動する桁数(空白桁数) 改行 / レコードの区切り w はデータの桁数 w は小数点を含む全体の桁数、 d は小数部の桁数 (例) 整数データの出力 (プログラム例) PROGRAM SEISU INTEGER I,J,K I=123 J=456 K=789 WRITE(*,1000)I,J,K 1000 FORMAT(' ',I6,I6,I6) STOP END (出力例) □□□123□□□456□□□789 *□は、空白を表します。 また、上記プログラム中の FORMAT 文のように同じ型が繰り返される場合は、 1000 FORMAT(' ',3I6) のように省略して記述することができます。 23 (例) 実数データ及び空白の出力 (プログラム例) PROGRAM JISSU REAL R,S,T R=123.0 S=456.2546 T=789.3333 WRITE(*,1000)R,S,T 1000 FORMAT(' ',F5.1,2X,F4.0,2X,F10.6) STOP END (出力例) 123.0□□456.□□789.333313 ※有効数字は7桁まで 5.2 入力 FORMAT READ 文と FORMAT 文を組み合わせることにより、入力形式を細かく指定できます。 READ(*,文番号) 入力並び 文番号 FORMAT(編集記述子の並び) 編集記述子に関しては出力 FORMAT と同じです。 nX の形式で記述すると読み取り位置が右に n 桁移動します。 例題 「ソート3(書式の指定)」 4章の例題で扱ったソート2のプログラムを改良し、FORMAT が決まったファイルから名前と点 数のデータを読み込み、点数でソートした結果を FORMAT 指定して新規ファイルに出力するプ ログラムを作成しなさい。指定する FORMAT は入力例/出力例を参考にしなさい。 (プログラム例) PROGRAM SORT3 INTEGER NUM(100),N,MAX,NUM2,I,J CHARACTER NAME(100)*10,NAME2*10 OPEN(UNIT=20,FILE='tensu.dat',STATUS='OLD') OPEN(UNIT=30,FILE='kekka.dat',STATUS='NEW') READ(20,1000) N READ(20,2000) (NAME(I),NUM(I),I=1,N) DO 100 I=1,N-1 MAX=I DO 200 J=I+1,N IF(NUM(J).GT.NUM(MAX)) THEN 24 MAX=J ENDIF 200 CONTINUE NUM2=NUM(MAX) NUM(MAX)=NUM(I) NUM(I)=NUM2 NAME2=NAME(MAX) NAME(MAX)=NAME(I) NAME(I)=NAME2 100 CONTINUE DO 300 I=1,N WRITE(30,3000) I,NAME(I),NUM(I) 300 CONTINUE CLOSE(20) CLOSE(30) 1000 FORMAT(I10) 2000 FORMAT(A10,I5) 3000 FORMAT(' ','No.',I3,':',2X,A10,I5) STOP END (入力データ(tensu.dat)の形式例) 10 T.Yamada H.Tanaka Y.Go R.J. K.Yoshida I.Ito P.Tanimoto K.Katsuta S.Kogawara K.Kotaka 80 65 91 100 54 47 96 87 38 43 (出力データ(kekka.dat)の形式例) No. 1: No. 2: No. 3: No. 4: No. 5: No. 6: No. 7: No. 8: No. 9: No. 10: R.J. P.Tanimoto Y.Go K.Katsuta T.Yamada H.Tanaka K.Yoshida I.Ito K.Kotaka S.Kogawara 100 96 91 87 80 65 54 47 43 38 25 第6章 副プログラム 6.1 主プログラムと副プログラム これまでに説明してきたプログラムは、1つのプログラムとして完結しているものでした。プログラ ムの構成によっては、同じような計算や処理手順を何回か実行する場合や、プログラムが大きくな って複雑になるようなことがあります。このような時に、目的ごとに小さなプログラムに分割して必要 に応じて呼び出すようにすれば、プログラムを作成する効率も良くなり保守性も向上します。プロ グラムの基本部分を主プログラムと呼び、主プログラムなどから呼びだされるプログラムを副プログ ラムと呼びます。副プログラムは個別にコンパイルし、リンク時に主プログラムなどと組み合わせて 1つの実行可能なプログラムを作ります。変数名も独立で、引数や COMMON 文などで定義しな い限り、同じ変数名でも主プログラム、副プログラムではそれぞれ個別の変数として扱われます。 副プログラムは、関数副プログラムとサブルーチン副プログラムに分類されます。 6.2 関数副プログラム 関数副プログラムは、組み込み関数として用意されていない関数を定義する場合に使用しま す。関数の定義ですので関数名自体に値を持つことができ、次に説明するサブルーチン副プロ グラムとの大きな違いです。 関数副プログラムは次の決まりに従って記述します。 ・ 先頭の文は FUNCTION 文であること。 ・ FUNCTION 文では関数の型、関数名、仮引数を指定する。ただし、関数の型がない場 合は暗黙の型宣言に従う。 ・ 仮引数は、この関数を呼び出すプログラムとの間でデータのやりとりを行うためのもので、 参照する側の引数(実引数)と、個数、型が一致していなければならない。 ・ 関数副プログラム内では、関数名を変数として扱い、呼び出したプログラムに戻るまでに 代入文などによって値を確定しなければならない。 ・ 関数副プログラム内で、RETURN 文あるいは END 文に出会うと、呼び出したプログラム に戻る。 関数の型 FUNCTION : 関数副プログラム名(仮引数の並び) 値の確定 : RETURN END 関数副プログラムの呼び出しは、組み込み関数を利用する場合と同じです。 引数で配列の全要素を指定する場合、配列名のみを指定します。 (例) A(10,10)を指定する場合 …… A とだけ指定 26 (例) XとYの値を受け取り、X2+Y2の値を返すような関数副プログラムと、その参照例。 (プログラム例) PROGRAM REAL 100 MAIN X , Y , Z READ(*,*,END=200) X , Y Z = FSUB1(X,Y) WRITE(*,*) X , Y , Z GOTO 100 200 STOP END REAL FUNCTION FSUB1(X,Y) FSUB1 = X**2 + Y**2 RETURN END 例題「Runge-Kutta の微分方程式」 Runge-Kutta(ルンゲ・クッタ)法によって、微分方程式 dy = x+ y dx の解を求めるプログラムを作りなさい。 ただし、初期値は x=1、y=1、x の増分を 0.1、とし x=2 までとする。 また、微分方程式で扱う関数は関数副プログラムで定義しなさい。 (解法) 微分方程式 dy = f ( x, y ) dx において、初期値を(x0 , y0)、xの増分をh、hだけ増分した点を(x1 , y1)とする。 このとき、y0からy1への近似増分kを次のような重みつき平均値として求める。 ここで求めた(x1,y1)を新たに(x0,y0)として繰り返す。 k 1 = f ( x 0, y 0 ) ⋅ h h k1 k 2 = f ( x0 + , y0 + ) ⋅ h 2 2 h k2 k 3 = f ( x0 + , y0 + ) ⋅ h 2 2 k 4 = f ( x 0 + h, y 0 + k 3) ⋅ h 1 y 1 = y 0 + ( k 1 + 2k 2 + 2k 3 + k 4 ) 6 27 (プログラム例) PROGRAM RK INTEGER I,STEP REAL X,Y,XN,H,K1,K2,K3,K4 READ(*,*)X,Y,XN,STEP H=(XN-X)/STEP WRITE(*,*)X,Y DO 100 I=1,STEP K1=FUNC(X,Y)*H K2=FUNC(X+H/2.0 , Y+K1/2.0)*H K3=FUNC(X+H/2.0 , Y+K2/2.0)*H K4=FUNC(X+H , Y+K3)*H Y=Y+(K1+2*K2+2*K3+K4)/6.0 X=X+H WRITE(*,*)X,Y 100 CONTINUE STOP END REAL FUNCTION FUNC=X+Y RETURN END はじめ 初期値、終値、 分割数を入力 X を初期値から終値 まで繰り返す K1,K2,K3,K4 を求める 新しい Y を求める X,Y を出力 おわり FUNC(X,Y) (入力例) 1.0 1.0 2.0 10 (出力例) 1.00000 1.00000 1.10000 1.21551 1.20000 1.46421 1.30000 1.74958 1.40000 2.07547 1.50000 2.44616 1.60000 2.86635 1.70000 3.34125 1.80000 3.87662 1.90000 4.47880 2.00000 5.15484 DO ループの初期値、終値、増分には整数を使用しましょう。 実数を使用した場合、誤差の影響で計算されない場合があります。 28 6.3 サブルーチン副プログラム サブルーチン副プログラムは、一連の処理の流れを独立させたものです。1つのプログラムで 同じような処理を何度も行う場合や、よく使うプログラムなどをサブルーチン副プログラムとして作 っておけば、必要に応じて呼び出すだけですみます。また、大きなプログラムは機能ごとにサブル ーチン副プログラムに分割すれば、プログラム全体が見やすくなりなり保守性も向上します。 サブルーチン副プログラムは次の決まりに従って記述します。 ・ 先頭の文は SUBROUTINE 文であること。 ・ SUBROUTINE 文ではサブルーチン副プログラム名、仮引数を指定する。 ・ 仮引数は、このサブルーチン副プログラムを呼び出すプログラムとの間でデータのやりとりを 行うためのもので、呼び出す側の引数(実引数)と、個数、型が一致していなければならな い。 ・ サブルーチン副プログラム内で、RETURN 文あるいは END 文に出会うと、呼び出したプロ グラムに戻る。 SUBROUTINE サブルーチン副プログラム名(仮引数の並び) : : RETURN END サブルーチン副プログラムを呼び出すには、CALL 文を使います。 CALL サブルーチン副プログラム名(実引数の並び) サブルーチン副プログラムから値を受け取りたい場合は、引数を通して行います。関数副プログ ラムについても言えることですが、サブルーチン副プログラム内で仮引数の値を変更すると、対応 する実引数の値も同じ値に変化します。 (例) XとYの値を受け取り、X2+Y2の値を返すようなサブルーチン副プログラムと、その参照例。 関数副プログラムの例に用いた問題で、サブルーチン副プログラムを使用した場合。 (プログラム例) PROGRAM MAIN REAL X , Y , Z 100 READ(*,*,END=200) X , Y CALL FSUB2(X,Y,Z) WRITE(*,*) X , Y , Z GOTO 100 200 STOP END SUBROUTINE FSUB2(X,Y,Z) REAL X , Y , Z Z = X**2 + Y**2 RETURN END 29 6.4 COMMON文 主プログラムと副プログラムのように、異なるプログラム単位でデータをやりとりする場合は引数 を使って行います。しかし、共有するデータや副プログラムの数が多くなった場合は引数での共 有だけでは不便です。このような時は、 COMMON 文を使って共有データを定義します。 COMMON 文の形式は次のとおりです。 COMMON [/共通ブロック名/] 変数名・配列名の並び COMMON 文では、共通ブロックを定義し、そこに変数の並びの順にデータを割り当てます。 共通ブロック名を指定しない場合は、無名共通ブロックを使うことを意味します。 データを共有するプログラム単位に、使用する共通ブロック名とデータに割り当てる変数名ま たは配列名を指定します。 (例) 主プログラムとサブルーチン副プログラムでデータを共有する場合。 (主プログラム例の一部) PROGRAM COMMON MAIN M , N , /BLK/ X , Y : (サブルーチン副プログラム1の例の一部) SUBROUTINE COMMON SUB1 I , J : (サブルーチン副プログラム2の例の一部) SUBROUTINE COMMON SUB2 /BLK/ A , B : このときのデータ共有の様子を図示すると次のようになります。 MAIN SUB1 M I N J SUB2 (無名共通ブロック) (共通ブロック名 BLK) X A Y B 30 6.5 整合配列 副プログラムを定義するときの仮引数には配列名も指定できます。この配列名は副プログラム 中でも配列宣言をしなければなりません。主プログラムでは配列の大きさを整定数で宣言します ので、プログラム作成時に配列の大きさを決定しなければなりませんでした。しかし、副プログラム 中では仮引数もしくは共通ブロックで定義した変数を使って配列の大きさを宣言することができま す。これを整合配列と呼び、副プログラムを呼び出すプログラムによって自由に配列の大きさが決 められるため汎用性が高くなります。ただし、2次元以上の配列の場合は、記憶領域の割り当てに よるズレが生じますので、最後の次元以外は配列の宣言時と同じ大きさで宣言します。 例題 「行列のかけ算2」 M行N列とN行L列の行列の積を求めるサブルーチン副プログラムを作り、以下のM×N行列 (ここでは2×3行列 A)とN×L行列(ここでは3×4行列 B)の積(ここでは2×4行列 C)を求 めなさい。ただし、行列のサイズはサブルーチン副プログラム内で決めるものとします。 3 6⎤ ⎡2 A= ⎢1 8 ⎥⎦ ⎣ 2 7 2 5⎤ ⎡2 B= ⎢6 2 1 4⎥ ⎢ ⎥ 7 2 5 ⎥⎦ ⎢⎣3 (解法) A(M,N)と B(N,L)の積 C(M,L)は以下の式で求まる。 n Cij = ∑ k =1 aik bkj (プログラム例) PROGRAM REAL MAIN A(10,10),B(10,10),C(10,10) INTEGER M,N,L,OSZ OSZ=10 READ(*,*) M,N,L READ(*,*) ((A(I,J),J=1,N),I=1,M) READ(*,*) ((B(I,J),J=1,L),I=1,N) CALL SEKI(A,B,C,M,N,L,OSZ) DO 100 I=1,M WRITE(*,*) (C(I,J),J=1,L) 100 CONTINUE STOP END 31 SUBROUTINE SEKI(A,B,C,M,N,L,OSZ) サブルーチン SEKI INTEGER I,J,K,M,N,L,OSZ 配列、変数の宣言 REAL A(OSZ,N),B(OSZ,L),C(OSZ,L) DO 100 I=1,M I を 1∼M, J を 1∼L まで繰り返す DO 100 J=1,L C(I,J)=0 総和を入れる変数を初期化 DO 100 K=1,N C(I,J)=C(I,J)+A(I,K)*B(K,J) 100 K を 1 から N まで繰り返す CONTINUE RETURN A,B の積を C に代入 END もどる (入力例) 2 3 4 ←行列A,Bのサイズ 2 3 6 1 2 8 ←2×3行列Aの要素 2 7 2 5 6 2 1 4 3 7 2 5 ←3×4行列Bの要素 (出力例) 40.0000 62.0000 19.0000 52.0000 38.0000 67.0000 20.0000 53.0000 例題 「最小二乗法」 (x1 , y1) (x2 , y2) (x3 , y3) ……. (xn , yn) といったデータの組が与えられた時、これを y(x) = ax+b で近似する事を考える。ここで、この式と実際のデータができるだけ一致するように、これらの 差の2乗和が最小となるような係数 a を決めるのが最小2乗法である。 解法で説明する式を使って、a、b を求めるサブルーチン副プログラムを作りなさい。なお、デ ータの個数と(x、y)の組はデータとして入力することとします。 (解法) a,b は次式で求めることができます。 a= n ∑ XiYi − ∑ Xi ∑ Yi ∑Y − a∑ X i b= n ∑ Xi 2 − ( ∑ Xi ) 2 32 n i n (プログラム例) PROGRAM JIJOHO REAL X(200),Y(200) I=1 100 READ (*,*,END=999) X(I),Y(I) I=I+1 GOTO 100 999 CALL SJH(X,Y,I,A,B) WRITE(*,*) A,' * X +',B STOP END SUBROUTINE SJH(X,Y,N,A,B) サブルーチン SJH INTEGER N,I REAL X(N),Y(N) 和を求める変数の初期化 REAL SX,SY,SXY,SX2 DATA SX,SY,SXY,SX2/0.,0.,0.,0./ DO 200 I=1,N I を 1 から N まで繰り返す SX=SX+X(I) X, Y, X*Y, X2 の和を求める SY=SY+Y(I) SXY=SXY+X(I)*Y(I) SX2=SX2+X(I)**2 200 CONTINUE A=(N*SXY-SX*SY)/(N*SX2-SX**2) B=SY/N-A*SX/N もどる RETURN END (入力例) 1 8 2 10 4 14 6 22 10 26 CTRL + D (出力例) 2.46005 * X + A, B を求める 3.90315 33 第7章 便利な利用方法 7.1 定数の便利な利用法 −PARAMETER 文− PARAMETER 文は定数を定義するためのものです。PARAMETER 文で定義される定数は 定数名によって型を持ちます。従って型宣言をなされていない場合は暗黙の型宣言に従います。 必要に応じて型宣言を行う必要があります。PARAMETER 文で値を定義された文字列は、コン パイル時に定義された値に変換されます。また、PARAMETER 文で用いる定数名は変数ではあ りませんので、プログラム中で値をかえることはできません。 PARAMETER 文は宣言文の後ろからプログラムの終わりまで、どこに入れても構いません。 PARAMETER (名前 1=値 1,名前 2=値 2,……,名前 n=値 n) PARAMETER (名前 1=値 1),(名前 2=値 2),……,(名前 n=値 n) (例) 定数 PI を 3.14159 として定義する例 PARAMETER (PI=3.14159) 配列の サイズは定数によって宣言されなければなりません。以下の例題のように行うと PARAMETER 文を修正するだけでプログラムの変更を簡単に行うことができます。 例題 「行列のかけ算3」 3章の例題「行列のかけ算1」において、PARAMETER 文を用いて行列サイズを簡単に変更 できるよう改良しなさい。 (プログラム例) PROGRAM MTRX2 PARAMETER (MSZ=4) REAL A(MSZ,MSZ),B(MSZ,MSZ),C(MSZ,MSZ) INTEGER I,J,K READ(*,*) ((A(I,J),J=1,MSZ),I=1,MSZ) READ(*,*) ((B(I,J),J=1,MSZ),I=1,MSZ) DO 100 I=1,MSZ DO 100 J=1,MSZ C(I,J)=0 DO 100 K=1,MSZ C(I,J)=C(I,J)+A(I,K)*B(K,J) 100 CONTINUE DO 200 I=1,MSZ WRITE(*,*) (C(I,J),J=1,MSZ) 200 CONTINUE STOP END 34 7.2 変数の便利な利用法 −DATA 文− DATA 文は変数、配列または配列要素に初期値を与えるもので、宣言文より後であればどこで も置くことができます。ただし、通常は DATA 文を実行文よりも前に置くようにしましょう。実行文の 中に DATA 文を置くことは、Fortran95 で(次回改正時の)廃止予定事項になりました。 DATA 名前 1/初期値 1/,……,名前 n/初期値 n/ DATA 名前 1,名前 2,……,名前 n/初期値 1,初期値 2, ……,初期値 n/ (例) 変数Aの初期値に 10.0 をセットする場合 DATA A/10.0/ サイズ 20 の実数型配列のすべての要素に初期値として 0.0 をセットする場合。 REAL B(20) DATA B/20*0.0/ 文字型変数に初期値をセットする場合 CHARACTER*8 STR DATA STR/'ABCDEFGH'/ 7.3 関数の便利な利用法 −文関数定義− 文関数は、文関数定義文で定義された関数で、同一プログラム単位内で引用できます。文関 数定義文の記述は、プログラム中の宣言文の後で、なおかつ最初の実行文の前に現れなければ なりません。形式は次のとおりです。 なお、文関数は Fortran95 で(次回改正時の)廃止予定事項になりました。関数副プログラム を使って文関数と同じ処理を実現できます。 文関数名(仮引数の並び) = 式 仮引数の並びは、文関数を引用する時の引数の順序、個数、型を示すためのもので、ここに 現れる変数名は文関数定義文の中だけで有効です。 例題 「文関数定義」 X2+Y2を文関数定義を用いて定義し、計算するプログラムを作成しなさい。 (プログラム例) PROGRAM MAIN REAL A , B , Z F(X , Y) = X**2 + Y**2 100 READ(*,*,END=200) A , B Z = F(A , B) WRITE(*,*) A , B , Z GOTO 100 200 STOP END 35 第8章 演習問題 8.1 Simpson の公式による数値積分 y=x3をSimpsonの公式を用いて 0∼1 の範囲で積分するプログラムを作りなさい。 [解説] Simpson の公式 a∼b の範囲で 2n をきざみとして積分する場合の例 ∫ b a b−a h= x 0( = a ), x1, x 2,・・・x 2 n − 1, x 2 n ( = b) とすると、 2n h f ( x ) = { f ( x 0 ) + f ( x 2 n ) + 4( f ( x1) + f ( x 3) + ・・・ + f ( x 2 n − 1)) 3 + 2( f ( x 2 ) + f ( x 4 ) + ・・・ + f ( x 2 n − 2 ))} 8.2 Gauss-Jordan 法(掃き出し法)による連立方程式の解法 次の連立一次方程式を、Gauss-Jordan 法を用いて解くプログラムを作りなさい。 ⎧ 2x1 + x2 - x3 = 1 ⎪ ⎨ x1 + 2x2 + x3 = 8 ⎪- 2x1 + x2 - x3 = -3 ⎩ [解説] 連立一次方程式の係数を行列にして、Gauss-Jordan 法を用いる。 1⎞ ・・・(1) ⎛ 2 1 −1 ⎜ ⎟ 1 8 ⎟ ・・・( 2) ⎜ 1 2 ⎜ − 2 1 − 1 − 3⎟ ・・・(3) ⎝ ⎠ (1)の 1 列目 A(1,1)の値が 1 となるように変形する。…(1)/2 …(4) 他行の 1 列目が 0 となるように、(4)を変形しながら引き算をする。…(2)-(4) , (3)-(4)*(-2) ⎛ 1 0.5 − 0.5 0.5 ⎞ ・・・(4) ⎜ ⎟ 1.5 7.5 ⎟ ・・・(5) ⎜ 0 1 .5 ⎜0 − 2 − 2 ⎟⎠ ・・・(6) 2 ⎝ ⎛ 1 0.5 − 0.5 0.5 ⎞ ・・・( 4) ⎜ ⎟ 2 1 8 ⎟ ・・・( 2) ⎜ 1 ⎜− 2 1 − 1 − 3⎟⎠ ・・・(3) ⎝ (5)の 2 列目 A(2,2)の値が 1 となるように変形する。…(5)/1.5 …(8) 他行の 2 列目が 0 となるよう、(7)を変形しながら引き算をする。…(4)-(8)*1/2 , (6)-(8)*2 ⎛ 1 0.5 − 0.5 0.5 ⎞ ・・・(4) ⎜ ⎟ 1 1 5 ⎟ ・・・(8) ⎜0 ⎜0 2 − 2 − 2 ⎟⎠ ・・・(6) ⎝ ⎛ 1 0 − 1 − 2 ⎞ ・・・(7) ⎜ ⎟ 1 5 ⎟ ・・・(8) ⎜0 1 ⎜ 0 0 − 4 − 12 ⎟ ・・・(9) ⎝ ⎠ (9)の 3 列目 A(3,3)の値が 1 となるように変形する。…(9)/(-4) …(12) 他行の 3 列目が 0 となるよう、(12)を変形しながら引き算をする。…(7)-(12)*(-1) , (8)-(12) ⎛ 1 0 − 1 − 2 ⎞ ・・・(7) ⎜ ⎟ 1 5 ⎟ ・・・(8) ⎜0 1 ⎜0 0 1 3 ⎟⎠ ・・・(12) ⎝ ⎛ 1 0 0 1⎞ ・・・(10) ⎜ ⎟ ⎜ 0 1 0 2 ⎟ ・・・(11) ⎜ 0 0 1 3 ⎟ ・・・(12) ⎝ ⎠ 最後に残った行列の A(4,j)成分が連立方程式の解となる。ここでは x1=1,x2=2,x3=3 である。 36 8.3 素数の判定 ある整数(N)を入力しその数が素数かどうかを求めるプログラムを作りなさい。 [解説] 素数判定の手順 (5) N を 2 でわる (6) 割り切れたら(あまりが 0 なら)素数ではない[終了] (7) 割り切れなかったら N を 3∼N/2 までの奇数 M(2 ずつ変化)で順にわる (8) 手順(3)のどこかで割り切れたら素数ではない[終了] (9) 割り切れなかったら素数[終了] 8.4 最大公約数と最小公倍数を求める 2 つの整数(N,M)を入力し最大公約数を求める。 [解説] 88,24 の最大公約数を求める例 大きい方 小さい方 あまり 88 24 (88÷24=3…16) 16 24 16 (24÷16=1…8) 8 16 8 (16÷8=2…0) 0 あまりが 0 になったときの割った数(小さい数)が最大公約数 もとの 2 つの整数(N,M)から最小公倍数を求める 最小公倍数 = N×M 最大公約数 8.5 自作sin関数(Maclaurin 展開とシステム sin 関数の比較) 角度 X(radian)を入力して、sin(X)を計算するプログラムを作成しなさい。このとき sin(X)の値 の計算には組み込み関数の sin を使用せず、Maclaurin 展開で求めた sin(X)を使って求め、組 み込み関数の sin との誤差を求めなさい。 [解説] Maclaurin 展開を使い sin(X)を求めると、以下のようになります。 X1 X3 X5 X 2 n −1 n −1 sin( X ) = − + − ... + ( −1) + ..... 1! 3! 5! ( 2n − 1)! 第1項 第 2 項目以降はその前の項を用いて簡単に求めることができる。 X の範囲は、0 から 2πの範囲とします。また、X の値に同じものを使用して、n を 5 から 15 の 範囲で変化させたときの、Maclaurin 展開で求めた sin(X)の値と組み込み関数の sin(X)で求めた 値とを比較してみましょう。 37 第9章 付録 9.1 利用できる文字 FORTRAN プログラム中では以下の文字が利用できます。FORTRAN では、英字 26 個、数 字 10 個、特殊記号 13 個を利用できます。英字の大文字と小文字を区別しないため、英字は 26 個を判別するのみです。 英字 ABCDEFGHIJKLMNOPQRSTUVWXYZ 数字 0123456789 特殊文字 = + − * / ( ) , . : (空白) ¥(通貨記号) 9.2 プログラムの構成 プログラム中の文の組立順序は以下のようになります。 PROGRAM 文、FUNCTION 文 、SUBROUTINE 文 PARAMETER 文 注 釈 行 FORMAT 文 他の宣言文 文関数定義文 DATA 文 実行文 END 文 9.3 演算子 算術演算子 意 味 関係演算子 意 味 + + .EQ. = − − .NE. ≠ * × .LT. < / ÷ .LE. ≦ ** べき乗 .GT. > .GE. ≧ 論理演算子 意 味 .NOT. 否定 .AND. 論理積 .OR. 論理和 .EQV. 論理等価 .NEQV. 論理非等価 文字演算子 // 38 意 味 文字列連結 9.4 命令文の分類 FORTRAN プログラム中の命令文は以下のように分類できます。 ここに示す命令文は FORTRAN で使用できる命令文の一部です。詳細については文法書な どを参考にしてください。 PROGRAM 文 PROGRAM プログラム名 プログラム単位の文 プログラム単位関係 FUNCTION 文 FUCTION 関数名(仮引数,…) SUBROUTINE 文 SUBROUTINE プログラム名(仮引数,…) INTEGER 文 REAL 文 (REAL*8 文) 型宣言関係 LOGICAL 文 COMPLEX 文 CHARACTER 文 非実行文 型名 変数名,… 宣言文 PARAMETER 文 PARAMETER (定数名=定数式,…) DIMENSION 文 その他 DIMENSION 配列宣言子,… COMMON 文 COMMON /ブロック名/ 変数,配列並び DATA 文 DATA データや変数の並び/定数並び/ 文関数文 文関数名(仮引数並び)=式 FORMAT 文 文番号 FORMAT(書式仕様) 39 算術代入文 代入文 代入文関係 論理代入文 文字代入文 DO 文関係 DO 文 DO 文番号 DO 変数=初期値,終値,増分 算術 IF 文 IF(算術式) 文番号 1,文番号 2,文番号 3 論理 IF 文 IF(論理式) 実行式 IF 文関係 ブロック IF 文 (ELSE 文、ELSE IF 文、END IF 文) IF(論理式) THEN : ENDIF 制御文 単純 GOTO 文 GOTO 文番号 GO TO 文関係 算術 GOTO 文 GOTO(文番号 1,文番号 2,…),整数式 実行文 CALL 文 CALL サブルーチン名 プログラム単位関係 RETURN 文 END 文 CONTINUE 文 その他 STOP 文 入力関係 出力関係 READ 文 READ(入力装置,書式)入力並び WRITE 文 WRITE(出力装置,書式)出力並び OPEN 文 OPEN(UNIT 指定子,FILE 指定子, 入出力文 ACCESS 指定子,FORM 指定子, STATUS 指定子,RECL 指定子,ERR 指定子, 補助入出力関係 IOSTAT 指定子,BLANK 指定子) CLOSE 文 CLOSE(UNIT 指定子,STATUS 指定子, ERR 指定子,IOSTAT 指定子)) 40 9.5 組み込み関数表 ここに示す関数名とは関数総称名です。詳細については文法書などを参考にしてください。 種類 関数名と利用法 機能 引数の数 最大値 MAX(A1,A2,…) 引数に指定されたものの中から最大値をわりだす ≧2 最小値 MIN(A1,A2,…) 引数に指定されたものの中から最小値をわりだす ≧2 平方根 SQRT(A) A 1 指数 EXP(A) e 自然対数 LOG(A) ln(A) 1 常用対数 LOG10(A) log(A) 1 正弦 SIN(A) sin(A) 1 余弦 COS(A) cos(A) 1 正接 TAN(A) tan(A) 1 逆正弦 ASIN(A) arcsin(A) 1 逆余弦 ACOS(A) arccos(A) 1 逆正接(1) ATAN(A) arctan(A) 1 逆正接(2) ATAN2(A1,A2) arctan(A1/A2) 2 双曲線正弦 SINH(A) sinh(A) 1 双曲線余弦 COSH(A) cosh(A) 1 双曲線正接 TANH(A) tanh(A) 1 絶対値 ABS(A) 剰余 MOD(A1,A2) 符号の付け替え SIGN(A1,A2) 切り捨て AINT(A) 四捨五入 ANINT(A) 四捨五入整数化 NINT(A) 型変換 A 1 |A| Re al ( A ) 2 + Im age ( A ) 2 A1-INT(A1/A2)*A2 A2≧0 ならば |A1| A2<0 ならば -|A1| 小数点以下を切り捨てる(整数型への変換と同じ) A≧0 ならば INT(A+0.5) A<0 ならば INT(A-0.5) A≧0 ならば INT(A+0.5) A<0 ならば INT(A-0.5) 1 2 2 1 1 1 INT(A) 整数型への変換 1 REAL(A) 実数型への変換 1 DBLE(A) 倍精度実数型への変換 1 CMPLX(A1,A2) 複素数型への変換 ICHAR(A) 1 文字を整数へ変換 1 CHAR(A) 整数を 1 文字へ変換 1 超過分 DIM(A1,A2) 文字長 LEN(A) A1>A2 ならば A1-A2 A1≦A2 ならば 0 文字列 A の長さ 41 1 または 2 2 1 9.6 アプリケーションサーバ(bosei)上での実習 (1)ログイン [スタート]→[プログラム(P)]→[ネットワーク] → [TeraTermPRO] を選択します。図のような画 面が表示されるので TCP/IP の欄に bosei を選 択して 「OK」 ボタンをクリックします。 次のようなメッセージが現れるので、「login:」 に対して自分のログイン名、「Password:」に対 してパスワードを入力します。パスワードは入力 しても表示されないので注意してください。 SunOS 5.8 login : 1axx1234 ← 各自のログイン名を入力します。 Password: ← パスワードを入力しても画面には表示されません。 : 101 1axx1234@bosei% ← セッションが開設された状態になります。 ここに表示される文字列をプロンプトといいます。 この状態でコマンドを入力することができます。 (2)プログラムの作成 ng エディタを利用してプログラムを作 成します。ここでは rensyu.f という名前の プログラムを作成します。 また、FORTRAN のソースプログラムの 終わりには「.f」を必ずつけるようにしてくだ さい。すると次の図のように、ng エディタの 画面になります。 1axx1234@bosei% ng rensyu.f ng エディタは、エディタを起動した後すぐに文字入力が行えますので、そのままプログラムを 入力してください。入力ミスの修正は BS キーで行ないます。カーソルの移動にはカーソルキー (↑,↓, →, ←)が使えます。 プログラム入力後、エディタを終了するためには CTRL キーを押しながら x、CTRL キーを押 しながら c を押します。すると次のメッセージが画面下に表示されます。 Save file /uhome/a/1axx1234/rensyu.f ? (y or n) 保存終了の場合はこのメッセージに対して y と答えます。 42 他にも ng エディタは以下のコマンドを使ってファイルを編集することができます。 カーソル位置から行末まで削除 CTRL - k カーソルの前の文字を1文字削除 BS カーソル上の文字を1文字削除 CTRL - d カーソルの位置に始点を設定 CTRL - SPACE で設定した始点からカーソル位置までを削除してバッ ファにコピー CTRL - SPACE で設定された始点からカーソルの位置までをバッファ にコピー CTRL - SPACE CTRL - w ESC w 削除やコピーでバッファに保存された内容をカーソルの位置に挿入 CTRL - y CTRL - x CTRL - c ng エディタの終了 ※ CTRL - k CTRL キーを押したまま k キーを押します。 ESC ESC キーを押した後、 w キーを押します。 w ※ 他にも利用できるコマンドは数多くあります。詳細は湘南計算機室ホームページ(http://www.cc.u-tokai.ac.jp/) から「オンラインマニュアル」−「エディタの使い方」−「ng エディタ」を参照してください。 (3)コンパイルとリンク 実際にプログラムを動かすためには、コンパイル・リンクという作業を行い、実行形式のプログラ ムを生成する必要があります。コンパイルとリンクは以下のコマンドで同時に実行できます。何も指 定をしないと a.out という名前の実行形式のファイルができあがります。 -o というオプションを使って実行形式のファイル名を指定することもできます。 1axx1234@bosei% f77 rensyu.f 1axx1234@bosei% f77 rensyu.f ←実行形式 a.out を作成 -o rensyu ←実行形式 rensyu を作成 作成したソースプログラム中に文法の誤りがあると、下のようにコンパイル時にエラーメッセージ が表示されます。 1axx1234@bosei% f77 rensyu.f rensyu.f: MAIN main: "rensyu.f", 5 行目: エラー: 分類不可能な文です。 1axx1234@bosei% この例ではプログラム名 MAIN のプログラムの5行目にエラーがあることを知らせていますので、 「(2)プログラムの作成」からやり直し、誤りを訂正後ファイルを保存し、「(3)コンパイルとリンク」に 進んでください。(「(9)実行の流れ」参照) (4)実行 コンパイル・リンクによって作成された実行可能形式のファイルをコマンドとして入力します。 [email protected]% a.out ←実行形式 a.out を実行 [email protected]% rensyu ←実行形式 rensyu を実行 ここで、入力データが必要な場合は、プログラム中に記述されているフォーマットに従って、デ 43 ータを入力します。 (5)入力ファイルと出力ファイル プログラム中に OPEN 文で指定されたファイルとは異なり、プログラム実行時に入力ファイルと 出力ファイルを指定することも可能です。入力ファイルは、「(2)プログラムの作成」と同じ方法でプ ログラムのフォーマットに従いデータを入力し、あらかじめ用意しておきます。出力ファイルは実行 時に指定して新規に作成します。ここでは、input という名前のファイルからデータを読みこみ、 output というファイルに書き出す例を示します。 [email protected]% a.out < input > output (6)結果の確認 「(5)入力ファイルと出力ファイル」で output に出力した結果を画面表示して内容確認します。 [email protected]% more output 1ページずつスクロールして画面表示されます。先の1行を表示するためには ENTER キー を、先の1ページを表示するためには SPACE キーを押します。 (7)プリントアウト 「(5)入力ファイルと出力ファイル」で output に出力された計算結果の印刷を行なう場合は以 下のコマンドを入力します。 [email protected]% lpr output (8)ログアウト セッションを終了します。bosei にログインをしたら最後には必ずログアウトが必要です。 [email protected]% logout (9)実行の流れ (1)ログイン エラー (2)ソースプログラムの作成(修正) (3)コンパイル・リンク (4)実行 (8)ログアウト 44