3日目「繰り返し処理」:準備
能書き
コンピュータは繰り返し同じ事をするのが得意です。 複雑な問題を「単純作業の繰り返し」に置き換えて解かせることが、プログラミングの目標と言えます。今日は「繰り返し」の感覚をつかんでください。
ファイルを作る
1.自分の"Fortran"フォルダに、"day3.f90"というファイルを作る2."day3.f90"を開く
3.下の"program... ...end program"をコピー&ペーストする
program day3 !------------------------ ! Fortran template !------------------------ implicit none integer, parameter :: double=selected_real_kind(15) !--- begin header --- !--- end header --- !--- begin main --- !--- end main --- end program
今更ですが
!コメント文『!』の右側は「コメント文」と言って、プログラムとは関係のない文章(主に説明)です。 何を書いても構いませんし、もちろん消しても構いません。
丁寧に説明文を書き込んでおくことで、後で自分が見たとき・他人が見たときにわかりやすくなります。
Lesson 8. 繰り返し処理
定義:doループ
do 整数型変数名 = 始値, 終値 [, 増分] {処理} end do『整数型変数名』を『始値』として{処理}を実行、
『end do』まできたら『整数型変数名』を+1(または、+『増分』)して{処理}を実行、
『end do』まできたら『整数型変数名』を+1(または、+『増分』)して{処理}を実行、
...
これを繰り返し、最終的に『整数型変数名』=『終値』となるまで{処理}を繰り返し実行する。
C++など他のプログラミング言語でも同様の命令があります。
実践
定義を見るとややこしいですが、使ってみればすぐにわかるでしょう。integer :: i do i=1,5 print *, "i = ", i end do結果はこうなります。
i = 1 i = 2 i = 3 i = 4 i = 5『i』を1から5まで変えながら、『do』と『end do』の間を5回実行しろ、という意味です。
『i』は繰り返しの回数を表すと同時に、整数型変数としてループ内で使うことができます。 ただしループ内で値をいじることは禁止です。
繰り返しの「回数」を表すループ変数は、実数型にしてはいけません。必ず整数型にしてください。 もし実数型の『x』を『1.0d0』から『5.0d0』まで変えたいときは次のようにします。
integer :: i real(kind=double) :: x x = 0.0d0 do i=1,5 x = x + 1.0d0 print *, "x = ", x end doループごとに、『x』の値が1.0d0ずつ増えていきます(>>復習)。
Lesson 9. 変数の初期化
学習: 変数の初期値
変数は、宣言された時点では値が「不定」である
というのがFortranの仕様です。
つまり、一度も値を代入せずに変数を使う(参照する)と、規則性のない値が出てくることになります。
試しに以下のようなプログラムを実行すると、
integer :: i1,i2,i3,i4 print *, i1,i2,i3,i4
コンパイラによってはエラーになります。
0 0 0 32767という結果になりました。この値には意味が無く、時と場合により異なります。 「たまたま0になることが多い」というのがくせ者で、 「今までちゃんと動いてたのに、急に変な値が出た」という面倒なバグを引き起こします。
変数を使う前には、必ず「初期化」(何か値を代入)するのを忘れないで下さい。
実践:「変数の初期化」
1から10までの自然数の和を求めるプログラムを作ってみましょう。面倒くさくても、コピー&ペーストせず自分の手で打ち込んだほうが練習になりますよ。
integer :: i, n, nSum n = 10 nSum = 0 ! initialize nSum do i=1,n nSum = nSum+i end do print *, "sum is ", nSumここで、
nSum = nSum+iというのは、「今の『nSum』の値を『i』だけ増やしたものを新しい『nSum』にしろ」という意味です。 ここでは命令が実行される前の『nSum』の値が重要で、 スタート地点を『nSum=0』とするのを忘れると、とんでもない値から始まってしまうことがあります。
変数は、参照する前に必ず初期化すること
実践:「変数のリセット」
「変数を何度も使う」時は、その都度適切に初期化(リセット)する必要があります。下のプログラムは、自然数の和を「和の公式」と「ループ」で計算して比べる(間違った)プログラムです。
integer :: i, n, nSum n = 10 !- formula version - nSum = n*(n+1)/2 print *, "(formula) sum is ", nSum !- loop version - do i=1,n nSum = nSum+i end do print *, "(loop) sum is ", nSum何がおかしいか分かりますか?プログラムを正しく書き換えてみましょう。
ループの前後での変数の値の変化をきちんと把握できるようになれば、ループの扱いは一人前です。
ちなみに、『(1/2)*n*(n+1)』は常に『0』です(>>復習)。気をつけましょう。
Lesson 10. キーボードからの入力
定義:read文(標準入力)
read *, 変数名プログラム実行を一時停止し、キーボードからの入力を待つ。
入力された値は『変数名』に代入される。
実践
キーボード入力を使った対話型のプログラムを組むと、格段に使い勝手が良くなります。上の「自然数の和」のプログラムに導入してみましょう。
n = 10の部分を、
print *, "n = ?" read *, nに置き換えて下さい。
何度か実行してみましょう。いちいちプログラムを書き換えてコンパイルし直すより楽ですね。
"n = ?"を表示するのは親切のためです。
問題2:nの階乗を求めるプログラムを作りなさい。
本日の問題です。いろいろな『n』で計算させてみて、答えが正しいことを確かめましょう。
ただし、『n』は10以下で試しましょう。値が大きすぎると桁があふれてしまいます。
答えが合わない人は、n=1のときの変数の値の変化を追ってみて、それでもダメなら解答を見てください。>>解答