それでは、話をwhileに戻します。
前回は合計の計算を行いましたので、合計を使ったプログラムの演習をしてみましょう。
「マイナスの表現」というコラムで2の補数を使えば減算を加算で行えるということを説明しました。
同じように、乗算も加算だけで行えます。
例えば、5×3は5に3を掛けるということですが、5を3回加算することで同じ結果が出ます。
5×3=15 5+5+5=15
答えの15は5と5と5の合計と言えます。
そこで、2つの整数を入力し、乗算した結果を表示するプログラムを作ってみてください。
ただし「*」は使わずにあくまでも「+」で作ってください。
<実行結果>
元の数を入力してください:5 掛ける数を入力してください:3 計算結果は15です。 続行するには何かキーを押してください・・・
解答例です。
<sample program 043-01>
#include <stdio.h> int main(void) { int input1; int input2; int sum; int counter; printf("元の数を入力してください:"); scanf("%d", &input1); printf("掛ける数を入力してください:"); scanf("%d", &input2); counter = 0; sum = 0; while (counter < input2) { sum += input1; counter++; } printf("計算結果は%dです。\n", sum); return 0; } |
<実行結果>
元の数を入力してください:5 掛ける数を入力してください:3 計算結果は15です。 続行するには何かキーを押してください・・・
これまで練習してきたカウンタと合計を使っています。
5×3であれば、5を3回加算するのですから、カウンタを使って3回繰り返すプログラムを書き、繰り返しの中で5を合計すれば良いのです。
違う方法で作った方も、色々な数を入力して試してみましょう。
例えば「0」を掛けるとどうなりますか?
答えは「0」になるはずですが、プログラムの作り方を失敗していると別の数値が出ることもあります。
「テスト」でも書きましたが、テストデータとして何を入力するかはよく考えなければなりません。
上のプログラムも色々試すと不完全だということが分かります。
何ができないか考えてみてください。
答えは「マイナスの乗算」です。
例えば−6×5は正しい結果が表示されます。
−6を5回加算すれば良いですから、問題ありません。
しかし、5×−6はどうでしょう?
5を−6回加算になりますから、−6回繰り返すことになります。
カウンタは「0」から始まります。
while (counter < input2) { |
の箇所でinput2には「−6」が入っていることになりますから、条件が不成立となり、一度も繰り返さずに終了します。
ですから、計算結果が「0」と表示されるわけです。
では、応急処置をしてみましょう。
<sample program 043-02>
#include <stdio.h> int main(void) { int input1; int input2; int sum; int counter; printf("元の数を入力してください:"); scanf("%d", &input1); printf("掛ける数を入力してください:"); scanf("%d", &input2); counter = 0; sum = 0; if (input2 < 0) { input2 = -input2; } while (counter < input2) { sum += input1; counter++; } printf("計算結果は%dです。\n", sum); return 0; } |
繰り返し条件の箇所でinput2がマイナスになっていると一度も繰り返さずに終了するため、input2がマイナスの場合は「プラスに変換」してみました。
input2 = -input2; |
変数の前に「-」をつけることで「符号を反転」できます。
では、実行してみます。
<実行結果>
元の数を入力してください:5 掛ける数を入力してください:-6 計算結果は30です。 続行するには何かキーを押してください・・・
おかしいですね。
5×−6の結果は「−30」になるはずですが、「+30」になっています。
5を−6回加算することができなかったため、「−6」を「+6」に変えました。
変えたことで、5を6回加算するプログラムになったわけですが、5を6回加算すると当然「+30」になります。
プログラムを修正する前にもう1つ試してみましょう。
<実行結果>
元の数を入力してください:-5 掛ける数を入力してください:-6 計算結果は-30です。 続行するには何かキーを押してください・・・
−5×−6の結果は「+30」のはずですが、「−30」になりました。
これも、−5を6回加算しているためです。
結局、マイナスをプラスに変換するだけでは正しい結果は得られません。
では、対処法を考えてみます。
上のプログラムの計算結果は「符合が反転」しているだけで、符号以外はちゃんとした合計結果が出ています。
そこで、右辺がマイナスであったかどうかを「覚えて」おき、マイナスであれば、「後で」符号反転させるという方法を取ってみます。
<sample program 043-03>
#include <stdio.h> int main(void) { int input1; int input2; int sum; int counter; int minus_flag; printf("元の数を入力してください:"); scanf("%d", &input1); printf("掛ける数を入力してください:"); scanf("%d", &input2); counter = 0; sum = 0; minus_flag = 0; if (input2 < 0) { minus_flag = 1; input2 = -input2; } while (counter < input2) { sum += input1; counter++; } if (minus_flag == 1) { sum = -sum; } printf("計算結果は%dです。\n", sum); return 0; } |
<実行結果1>
元の数を入力してください:5 掛ける数を入力してください:-6 計算結果は-30です。 続行するには何かキーを押してください・・・
<実行結果2>
元の数を入力してください:-5 掛ける数を入力してください:-6 計算結果は30です。 続行するには何かキーを押してください・・・
正しい結果が得られました。
右辺がマイナスであるかどうかを「覚えて」おくために「minus_flag」という変数を用意しました。
変数「minus_flag」は、右辺がマイナスであれば「1」が、右辺が0またはプラスであれば「0」が入ります。
計算を終えた後、「minus_flag」が「1」であれば、計算結果の符号を反転させています。
ここで、flag(フラグ)という考えについて書きます。
フラグとは状態を表すスイッチのようなものです。
例えば「minus_flag」というのは、右辺がマイナスであれば「1」(つまりスイッチがONの状態)であり、マイナス以外であれば「0」(つまりスイッチがOFFの状態)を表しています。
プログラムを実行していく過程で、フラグの中身をチェックし、分岐させていくのです。
ゲームの世界でも良く使われていて、RPGを例にすると、
ゲームが始まった時点では、城や町から出られなくなっています。
しかし、王様等と話をすることで、城や町から出られるようになります。
この場合、ゲーム開始時点では城や町から出られる「イベントフラグ」がOFFになっており、王様等と会話することで「イベントフラグ」がONになっているのです。
色々な場面で使われる「フラグ」ですが、あまり大量に設定するとプログラムが煩雑になり、不具合が発生した際にデバッグが困難になります。
実際の仕事等で乗算を加算で行うプログラムを書くことはまず無いでしょう。
「*」という演算子があるのですから、わざわざ加算で乗算を行う必要など無いのです。
今回はプログラムの練習ということで題材として取り上げてみました。
次回は、除算を減算で行うということをやってみましょう。