第3回、判断と飛び越し


目次


判断と飛び越し

先週の例題、課題によって”プログラムは上から下へ向かって実行される” というごく常識的な判断が通用する、ということが理解できたと思います。 今日は特定の条件によってプログラムを分岐させる方法を説明します。また ついでですので、プログラムのbrush upの方法も同時に示しましょう。

例題
3つの数a, b, cを読み込み、2次方程式 ax2 + bx + c = 0 の解を 出力しなさい。
まずは、先週までの知識+αでプログラムを書くと次のようになります。
解答1
       integer a, b, c
       real x1, x2
c
       read(5,*) a, b, c
       x1 = ( -b + sqrt( b*b - 4.0 * a * c ))/ (2.0*a)
       x2 = ( -b - sqrt( b*b - 4.0 * a * c ))/ (2.0*a)
c
       write(6,*) x1, x2
c
       end
いくつかの入力データに対してはきちんと結果を出してくれますが、そうは ならない場合があり、つまり上のプログラムには重要な欠陥がいくつかあり ます。
  1. 入力される係数が整数に限定されていること。
  2. "a"にゼロが入ってしまうとプログラムは正常に動作しない。
  3. 関数"sqrt"(平方根を求める組み込み関数)の中は常に正でなければ ならないが、それが保証されていない。
  4. 桁落ちが発生する可能性がある。
WWWのCGIプログラムを書く時はよく”ユーザーの入力 データを仮定してはいけない”と言われています。今日の講義の主題の 1つはここにあって、プログラムの方でいろいろなユーザーからの入力データ にもたえうるような、ある意味で”がんじょうな”プログラムを作ろう、と しているわけです。
順番に対策を講じていきましょう。1.は単に変数宣言しているところを"integer"から "real"に変更すればいいですね。楽勝。楽勝。

2.はIF文を使ってプログラムの流れを変えてやります。
解答2

       real a, b, c
       real x1, x2
c
       read(5,*) a, b, c
       if( a .eq. 0.0 ) then
          x1 = - c / b
          x2 = 0.0
       else
          x1 = ( -b + sqrt( b*b - 4.0*a*c ))/ ( 2.0*a )
          x2 = ( -b - sqrt( b*b - 4.0*a*c ))/ ( 2.0*a )
       end if
c
       write(6,*) x1, x2
c
       end

3.も2.の場合と同様、IF文で解決させましょう。
解答3

       real a, b, c
       real x1, x2
c
       read(5,*) a, b, c
       if( a .eq. 0.0 ) then
          x1 = - c / b
c
          write(6,*) 'x1 = ', x1
c
       else if( (b*b-4.0*a*c) .lt. 0.0 ) then
c
          write(6,*) '***** root is imaginary *****'
c
       else
          x1 = ( -b + sqrt( b*b - 4.0*a*c ))/ ( 2.0*a )
          x2 = ( -b - sqrt( b*b - 4.0*a*c ))/ ( 2.0*a )
c
          write(6,*) 'x1 = ', x1, ' x2 = ', x2
c
       end if
c
       end

4.はちょっと理解しにくいですね。実は b の絶対値と b*b-4*a*c の平方根の絶対値 が近い値の時桁落ちが起きてしまいます。これを 避けるためには

  x1 = (-b - (sgn(b))* sqrt(b*b-4*a*c))/ (2*a)
ここで
  sgn(b) = 1 (b>=0) or -1 (b<0)
また他の解は解と係数の関係
  x2 = c / (a*x1)
から求める方が適切といえます。

今日の課題

  1. 小テスト
  2. [3-1]上の例題の続きである。2次方程式を解くためのプログラムを完成させよ。 以下の条件まで対応している方がのぞましい。入力データ、出力データは 数種類ある方がよい。
    1. 虚数解もきちんと出力できること。
    2. 数値計算上の精度の問題もクリアーしていること。
  3. [3-2]鶴と亀の頭の数の合計と足の数の合計を読み込み、鶴と亀の数を求めよ。 本日の例題のようにいろいろなケースを想定し、プログラムを作成すること。

本講義の目次へ戻る