2019.11.23すごいとは思わないけれど、何か気になるFORTRAN。FORTRAN学習の先には何かある予感がします。学習の先に何もないかもしれないし、すごい悟りを得るかもしれない。学校でFORTRANの実習したときもそうだったのですが、FORTRANで何ができるんだろう、と不思議に感じます。いろんなことができるんでしょうけど。若い時に真面目に勉強しておけば、今FORTRANやり直しすることもなかったかもしれませんが、その時にFORTRANで感動が起こらなかったのでしょうがないです。当時言われていたFORTRANやCといった高級言語よりも、私はアセンブラが面白くて仕方がなかったので、高級言語をまったく学ぶ気がありませんでした。今はコマンドにハマってますので、どちらかといったら高級なのでしょうけど。FORTRAN77覚えようと思います。(90や95も)世界初の高級言語なので、いつか使えるようになればいいと思っていましたが、今回から始めることにしました。TRANslationが由来だそうです。コンパイラはgfortranを使うことにします。95系77系両方使えます。6LinuxでFortranことはじめインストールインストールは簡単。apt-get使うだけです。Worldを作ってみます。hellotakk@deb9:~$プログラムの開始と終了の位置を指定する必要があります。ビルド(コンパイル)ビルドは、gfortranを実行します。デフォルトの実行ファイルはa.outです。ソースファイルの拡張子をf95にして、ビルドする時に何もつけないとFORTRAN95でのビルドになります。Worldtakk@deb9:~$FORTRAN77でビルドするには、拡張子を.fにして、-std=legacyを指定します。1コマンドラインを使いこなす上で、プログラミング知識も必要かと思い、いろんな言語を少しずつ学習していますが、FORTRANを理解するのが一番苦労してるかもしれません。世界初の高級言語でスパコンにも使われている。66,77,90,95といった制定された年別に言語仕様が存在する。Worldを書いてみたものの、果たしてFORTRAN77にPRINT命令があったかどうかわかりません。いうか、手元のFORTRAN77の教科書に書いてないです。リファレンスには、いったいどこを見ればよいのでしょう。それもおいおい調べていきます。今回は、手元の古い教科書を頼りに、print文ではなく、WRITEとFORMATを使って表示をしていきたいと思います。サンプルプログラムです。ENDtakk@deb9:~$A=500.5は、変数Aに500.5という数値を代入しています。WRITEと次の行のFORMATはセットで使うのですが、WRITE関数の第2引数の123というのが、どの書式を使うのかの指定になります。適当に123というラベル名をつけてますが、存在しないラベルを指定してはいけません。以下のようにエラーになります。definedtakk@deb9:~$ラベルなのだから文字列でもいいのかと思いきや、思いっきりエラーになります。INTEGERtakk@deb9:~$そもそも6カラム目までは行番号を各エリアなので、整数が基本です。桁数が多くてもエラーとなります。(1)takk@deb9:~$5桁までのようです。./a.outA=500.50takk@deb9:~$ラベルの数字は上の桁を0としても良いようです。2FORMATのラベルの順番は数値の大小関係ないようです。./a.outA=500.50HELLOtakk@deb9:~$FORMATを定義する位置はどこでもよさそう。./a.outHELLOA=500.50takk@deb9:~$変数を指定しているのに、FORMATで書式を指定していないと実行時にエラーになります。0xfffffffffffffffftakk@deb9:~$FORMATの引数は、複数指定可能です。./a.outAAABBBCCCtakk@deb9:~$空白文字は数を指定できます。AAAとBBBの間に10個の空白を入れたい場合は、10Xと指定します。いうと、まだ覚えてません。FORMAT記述子I前回使ったように、クォートで囲った文字列をカンマをつけて引数に指定すると、文字列が連続で表示されますね。./a.outAAABBBCCCtakk@deb9:~$改行にするには、カンマをスラッシュにすれば良いようです。これは到底思いつかないです。古い教科書が頼りでした。./a.outAAABBBCCCtakk@deb9:~$次は数値の書式です。FORTRANのFORMATの数値の記述子には以下があります。整数型の記述子Iから。このような簡単なプログラムで確認します。ENDtakk@deb9:~$ビルドして実行してみましょう。0xfffffffffffffffftakk@deb9:~$なぜエラー・・・?エラーメッセージにREALとあるので実数型になってるのでしょうか。整数型にしてみましょうか。WRITE文で指定している変数AにINT関数を適応してみました。200takk@deb9:~$ビルドが通ってびっくり。INT関数で整数型になったということは、A=200は実数なんでしょうね。整数の宣言が必要なのでしょうか。整数の変数宣言はINTEGERを使うようです。宣言してから使ってみます。200takk@deb9:~$今度はエラー出ませんでした。最近のスクリプトのように、変数の型宣言なしで使うのは危ないってことでしょうね。FORTRANのことが毎日少しずつ分かってきてる気がします。E実数型のFORMATの記述子、F、Eについて使ってみます。F10.3は、小数点を含んだ全部の桁数が10で、小数点以下の桁数が3という意味です。実行すると、このように表示されます。123.450takk@deb9:~$Fで指定する桁数が不足している場合は、値の代わりに*が表示されます。./a.out******takk@deb9:~$上記ではF6.3なので、123.450と表示が期待されますが、全桁数は6なので1不足しており、*の表示になっています。F7.3にすると以下のように表示されます。./a.out123.450takk@deb9:~$次はEです。E全体桁数.小数点以下桁数で指定します。0.12E+03と表示されました。FORMAT記述子GFORMATの記述子Gを使います。Gは、自動で判別して、FまたはEの書式で表示します。ENDtakk@deb9:~$実行結果です。0.12E+03takk@deb9:~/gf$C言語のprintfの書式にも%Gがありますが、素通りしてました。今回初めて意味を知りました。Gという文字を使うのかは謎です。C書式に対応しているprintfコマンドで確認してみます。123.45takk@deb9:~$FORTRANのFORMATよりも分かりやすいです。全体を10桁右詰で表示し、仮数部を5桁で表示してますね。printfを知ってしまったら、FORTRANの方のG10.5の10はいったい何の意味があるのでしょう、と疑問。printfを10.5gから10.2gまでの結果を並べてみてみます。printfはてっきりFORTRANを参考にしたとばかり思ってましたが、どうなんでしょう。300.90takk@deb9:~$F7.2の記述は、なんと、まとめることができます。このようにFの前に添え字(3)をつけると、同じ指定子が添え字で指定した数だけ繰り返して書式設定されます。300.90takk@deb9:~$驚きです。数学チックな書き方かと思います。次は各値を改行して表示してみます。300.90takk@deb9:~$添え字に3を指定して記述子を一つにまとめたいと思います。300.90takk@deb9:~$一行で表示されていました。実は添え字の3が適用されているのは、F7.2までなので、最後の一回だけ改行が表示されているんです。各値の表示後に改行するには、添え字の適用範囲を()で囲えばよいです。1私が参考にしてる1993年頃のFORTRAN入門書には変数名の規則として、「英字で始まる6文字以内」と書かれています。当時はそうだったのかもしれませんが、今はもっと長い名前が使えるようです。./a.out123.45takk@deb9:~$変数名の長さがどのぐらいまでいけるのか簡単なスクリプトで確認してみます。<FH>;close(FH);}takk@deb9:~$指定した変数名の長さのFORTRANプログラムtest.fを生成して、ビルド後、実行するスクリプトになっています。引数には確認したい変数の長さ(開始、終了)を指定します。1文字の変数の確認をしてみましょう。Aという1文字の長さの変数を使ったプログラムを生成し、ビルドして実行しました。最後にビルドしたソースは残ってますので確認してみます。ENDtakk@deb9:~$次は2文字から10文字ぐらいを確認してみます。ENDtakk@deb9:~$10文字ぐらいは余裕で大丈夫ですね。次は変数の長さを100文字にして確認してみましょう。takk@deb9:~$あれ、100文字ではビルド通りませんね。半分の50文字を確認してみます。123.45takk@deb9:~$通りました。その半分の75文字をみていきます。takk@deb9:~$面倒なので51から74まで一気に確認します。test.f:2:70:64文字でビルドエラーになりましたが、その前から結果が怪しくなっています。長い名前にはしない方が良いということですね。変数名は英小文字も使えるようですが、大文字と区別されないようです。BASICと同じですね。BASICはFORTRANの文法が基になっているようですので当然ですね。配列の添え字は1始まりです。30takk@deb9:~$配列はすんなり理解できそうなので、次に繰り返しをしてみます。DO~CONTINUEを使います。50takk@deb9:~$DOで指定するのは、CONTINUEがある行のラベル名と、繰り返しの範囲です。ラベルは必要ないような気もしますが、こんなこともできます。3takk@deb9:~$少し感動しました。FORTRANの学習を初めてよかったなあ、と。BASICのFOR~NEXTでは、NEXTは2か所必要でしたが、FORTRANではまとめて書くことができるんです。DOの行も範囲をすっきり指定できますし、優れた文法を持っているんですね。あと、忘れていましたが、変数Iと変数Jについて、いつのまにか整数型になっています。実は、I~Nで始まる変数名は、デフォルトで整数型になります。200takk@deb9:~$思いもよらない変数名の仕様です。古い言語ですが、新しい発見があって面白いです。1FORTRAN、少しずつ学習しているうちに面白くなってきた気がします。キーボードから入力するには、第1引数に*アスタリスクを指定します。第2引数は、FORMAT文がある行のラベルを指定します。ENDREAD文の行でキーボードからの入力待ちとなります。入力した数字が、変数Iに格納されます。333takk@deb9:~$複数の数字を入力するプログラムに改造してみます。カンマで区切って指定すればよいかと思います。0takk@deb9:~$なんてことでしょう。2つの変数に入力したいのに、改行を押したとたん処理が進んでしまいました。2回に分けないといけないのでしょうか。200takk@deb9:~$確かにREADを2回に分けると確実ですね。WRITEがカンマで区切って変数指定できるのに、なぜでしょう。ここ数日の学習内容を見返して改行について思い出しました。FORMATをカンマの代わりに/を使えば改行になるんでしたね。200takk@deb9:~$感でしたが、動きました。直感で使える言語というのは優れた言語であろうと思いますが、FORTRANもそうなんですね。おさらいREADのおさらいです。30takk@deb9:~$,(カンマ)で区切った場合、入力できないと思い込んでいましたができました。キーボードから入力する値を,(カンマ)で区切ればよいだけでした。30takk@deb9:~$実はREAD文だけで、FORMATも必要ありません。30takk@deb9:~$このように、READの第2引数も*にしておけば、,(カンマ)で区切った数値を各変数に代入できます。この方法のすばらしさが、改行にも使えるということ。30takk@deb9:~$READはFORMAT要らないですね。,(カンマ)や、Enterキーの入力が面倒な場合は、スペースキーで区切ることもできます。30takk@deb9:~$,とEnterの混在でも認識してくれます。30takk@deb9:~$指定された変数以上に値がある場合はどうなるでしょうか。30takk@deb9:~$最初の2値のみ代入されたようです。ありがちなプログラミング言語のif文は、こんな形かと思います。ifFORTRAN(77の昔の教科書を見ています)は当然元祖なので、この形になります。実際のプログラムを見てみると戸惑います。THENELSEENDIF括弧の中の、X.EQ.1という記述。何が書いてあるのか分かりませんでした。学生時代にもきっと学習した筈なんですが。1ああ、Xが1と同値の時か。ピリオドが空白になるだけで、だいぶ違って見えます。ピリオド=メンバやメソッドという固定観念が植えられてしまっているので、X.EQ.1の様な表記だとどうしても頭に入ってこないんです。一回謎が解ければもう簡単です。条件式の書き方が分かったところで、数字を入力して20より上かどうか判定するプログラムを作ってみます。Than(より大きい)の略です。20takk@deb9:~$条件式には以下のものがあります。)では、もう少し複雑な式にします。20より大きく30以外の場合のみ表示するプログラムを作ります。関数サブルーチン関数は、FUNCTIONですが、まずはサブルーチンから使います。サブルーチンを作るには、SUBROUTINEを使います。ENDtakk@deb9:~$サブルーチンHELLOを実行するには、CALLが必要みたいです。VBのSUBの元はSUBROUTINEだったということも分かりました。プログラムを実行してみます。./a.outHELLOtakk@deb9:~$次は関数です。関数はFUNCTIONで定義します。戻り値を設定するには、関数名に代入してやればよいです。ENDtakk@deb9:~$実行結果です。30takk@deb9:~$次は、またサブルーチンですが、引数ありのサブルーチンです。C言語ばかりやってきた私としては、ポインタや参照を使わないのに引数で戻り値を返せるというところにびっくり。いろんな言語の祖先だけあってFORTRANは結構柔軟にできてるんですね。組み込み関数を使用して計算してみます。2.24takk@deb9:~$SQRTは平方根を求める関数ですが、他の言語だとして使う時にインポートしたりインクルードしたりいろいろ必要ですが、FORTRANの場合はそのまま使えます。他の計算もしてみましょう。0.58takk@deb9:~$文関数FORTRANは偶然大文字で記述していましたが、新しいFortranは、もう言語が違うんじゃないかってぐらい古いFORTRANと異なっているらしくて、新旧区別するためにFORTRANとFortranというように記述を分けてるらしいです。合ってましたが、知らずに全大文字表記を使ってました。今回は、文関数を使います。定義方法の違いを見るため、まず普通の関数(かつては副関数と呼ばれていた)をおさらいします。ENDまるで違いますね。文関数はとても数学的に書けます。何か作ってみましょう。77では、円周率の定数が無いようですので、PIを返す文関数を作ってみます。OPEN関数の各引数には、キーワードがついています。Pythonのキーワード引数と似てますね。FORTRAN77の頃からこの指定方法があったんですね。OPENの次の行に、1ACCESSとありますが、1は前行の続きの意味です。空白以外ならOKですが、続きの行数がわかるように1と書いています。330takk@deb9:~$sample.txtにデータが保存されました。こんな書式で格納されるんですね。それにしても引数のキーワードって分かりやすいですね。つけていれば分かりやすいですが、行をまたぐのは嬉しくないので、引数の各キーワードが省略できるか確認してみます。(1)takk@deb9:~$ダメでした。省略できるのは、先頭のUNITのみのようです。ファイル読み込みファイルを読み込みしてみます。catで見るとこのようなデータになっています。330takk@deb9:~$読み込みのプログラムは書き込みプログラムをWRITEからREADに変えればよいです。その際、OPENのSTATUSはOLDにします。OLDという表現が妥当かどうか分かりませんが、既存ファイルの意味です。実行すると各変数に各データが格納されていることが分かります。330takk@deb9:~$読み込みファイルのフォーマットは、どうやら空白がデータの区切り文字となっているようですが、空白の数はいくつでもよいのでしょうか。330takk@deb9:~$空白一つでも問題ないようです。100個ぐらいの空白を入れて確認してみましょう。209なので、サイズは一致しますね。330takk@deb9:~$問題なく読み込みできました。読み込む時に指定する書式が間違っているとどうなるのでしょうか。0空白を無視して読み込まれました。文字列FORTRAN77のことは分かってきたつもりですが、いまだにまったく使えていないのが文字列です。プログラマーの感を働かせても使い方がまったく分かりません。相変わらず古い教科書が頼りです。‘hello’とやるだけで使えてしまいますが、FORTRAN77では、宣言が必要です。文字列のサイズも指定してやる必要があります。