5日目「条件分岐」:準備

能書き

プログラミングの要素は色々ありますが、エッセンスと言えるのが「繰り返し」と「条件分岐」です。
これらはほぼ全てのプログラミング言語が備えている基本的な機能で、 プログラムの内部で行われる処理は、この2つの組み合わせでできている、と言っても良いでしょう。
今日までの内容が理解できれば、プログラミングの基本は大丈夫です。

ファイルを作る

program day5
 !------------------------
 ! Fortran template
 !------------------------
 implicit none
 integer, parameter :: double=selected_real_kind(15)
 !--- begin header ---

 !--- end header ---
 !--- begin main ---
  
 !--- end main ---
end program
Lesson 13. 条件分岐

定義:if文

 if (条件式) then
    {処理}
 [else if (条件式2) then
    {処理2}]
 [else if (...) then
    {...}]
 [else
    {処理3}]
 end if
『条件式』が「真」(満たされている)ならば{処理}を実行する。
[そうでなくて(『条件式』が「偽」で)『条件式2』が「真」ならば{処理2}を実行]
[それ以外は{処理3}を実行]
どの条件にも当てはまらず、かつ『else』がなければ何もしない。

定義:条件式(論理式)

 等しい『==』、異なる『/=』、大なり『>』、小なり『<』、以上『>=』、以下『<=』
「等しい」はイコール2つです。「代入」の『=』と混同しやすいので注意。
『=>』『=<』のように順番を入れ替えてはいけません。2つ合わせて1つの記号です。
両辺を評価し、式を満たせば『.TRUE.』(真)を、満たさなければ『.FALSE.』(偽)を返す。

 かつ『.AND.』、または『.OR.』
2つ以上の条件式をつなぐ。
例)0 < x < 1
 (0.0d0 < x) .AND. (x < 1.0d0)
『0.0d0 < x < 1.0d0』は許されません。

学習

「もしx>aならこっち、それ以外の場合はこっち」という単純な分岐や、 「i==0のときだけ実行する」といった例外的な処理など、 条件分岐は様々な場面で使います。
「論理式」は単純な場合は普通の条件式の感覚で扱えるのですが、 複雑な条件になると注意が必要です。
さらに「多重条件分岐」となると相当複雑になってしまいます。 条件分岐を扱うコツは、
なるべく複雑な条件を課さない
ことです。状況を整理し、単純化してください。

階段関数のプログラムです。
 real(kind=double) :: theta, x
 
 print *, "x [real] = ?"
 read  *, x

 if (x > 0.0d0) then
    theta = 1.0d0
 else if (x == 0.0d0) then
    theta = 0.5d0
 else
    theta = 0.0d0
 end if
 print *, "Heaviside step function: theta(", x, ") = ", theta
条件(else if...)が複数ある場合は上から順に判断され、当てはまった場所より下はスキップされます。
逆に、下の方の条件は自動的に上の方の条件(を満たさないこと)を含んでいるため、 最後の条件『else if (x < 0.0d0) then』をあえて書く必要はありません。

問題:ax2 + bx + c = 0を場合分けで丁寧に解け

Lesson 6では複素数を使って「2次方程式」を解きましたが、 今回は方程式「ax2 + bx + c = 0」について
複素数型変数を使わずに、どんな実数a,b,cに対しても正しく答えを出す
プログラムを作ってください。
高校時代を思い出しつつ場合分けを使って丁寧に解いていきましょう。
問題にまわりくどい制約をつけたのは、
どのような場合にエラーが起きるかを考えて、それを回避する
練習をしてもらうためです。 真面目に考えると案外(相当?)大変ですが、頑張ってみて下さい。
ヒント:「2次方程式であり、かつ判別式が正」の場合はLesson 6のプログラムになります。

実数の範囲で解を持たない(解が複素数になる)場合は、 最後に次の関数を使って複素数に変換してください。
2つの実数から複素数を作る
 cmplx(実部,虚部,kind=double) 
>>解答
全然分からなかった人は、解答をじっくり眺めて理解した後、自分の手で改めてプログラムを組んでみて下さい。

蛇足

if(条件式) {命令}
のように、thenとend ifを省略して1行で書くことも出来ます。(当然、「命令」が1行だけの時)
最初のうちは混乱するので使う必要は無いですが、著者がつい使ってしまうので紹介だけしておきます。
コードを短くできます。
Lesson 14. ループの制御

応用

if文とdo文を使いこなせれば、発想次第で色々なプログラムを作ることができます。
物理からは離れますが、じゃんけんのプログラムです。 コピーペーストして実行してみましょう。
 integer :: i, jan, kaisuu
 
 print *, "### Janken vs. Mr. Atoda ###"
 kaisuu=1
 do while (kaisuu <= 3)      ! 3回戦まで
    print *
    print *, kaisuu, "kaisen"
    print *, "1:gu, 2:chi, 3:pa, 0:end"
    read  *, jan
    if (jan==1) then         ! グー
       print *, "anta : gu"
       print *, "washi: pa"
    else if (jan==2) then    ! チョキ
       print *, "anta : chi"
       print *, "washi: gu"
    else if (jan==3) then    ! パー
       print *, "anta : pa"
       print *, "washi: chi"
    else if (jan==0) then
       exit                  ! 『0』が入力されるとループを抜ける
    else
       print *, "mou ichido."
       cycle                 ! 1,2,3,0以外の値が入力されたら、ループの先頭からやり直し
    end if
    print *, "washi no kachi. anta no make."
    kaisuu = kaisuu+1        ! 決着がついたら回数カウンタを+1
 end do 
色々と新しい命令が出てきたので1つずつ説明します。
 do while(条件式)
というのは、「もし「条件式」が満たされていれば繰り返す」という意味で、 if文とdo文が合体したようなものです。
 exit
というのは「doループを出ろ」という意味、
 cycle
は「doループの先頭に戻れ」という意味です。
それぞれif文と組み合わせることで、doループの柔軟な制御が出来ます。
これらを念頭において読み直してみると、何をしているのか分かるでしょう。

それにしても、Atoda氏は卑怯ですね。次は、もう少し公平なプログラムを考えます。