それでは、除算を減算で行うプログラムを考えてみましょう。
乗算は加算を繰り返すことで出来ました。
除算は減算を繰り返すことで出来ます。
13÷4を考えてみます。
13÷4の答えは「3.25」ですが、小数以下を考えると難しくなるので、「商と余り」という形で計算します。
13÷4の商は3、余りは1です。
これを減算を繰り返す方法で考えてみると、
13−4=9 9−4=5 5−4=1
この時点で1から4を減算するとマイナスになりますので、計算を止めます。
減算は3回行っています。
最後の計算の答えは1です。
これが商と余りになります。
最初はマイナス等は考慮しなくて構いませんので、考えてみてください。
<実行結果>
元の数を入力してください:13 割る数を入力してください:4 商は3、余りは1です。 続行するには何かキーを押してください・・・
解答例です。
<sample program 044-01>
#include <stdio.h> int main(void) { int input1; int input2; int syou; int amari; printf("元の数を入力してください:"); scanf("%d", &input1); printf("割る数を入力してください:"); scanf("%d", &input2); syou = 0; amari = input1; while (amari >= input2) { amari -= input2; syou++; } printf("商は%d、余りは%dです。\n", syou, amari); return 0; } |
<実行結果>
元の数を入力してください:13 割る数を入力してください:4 商は3、余りは1です。 続行するには何かキーを押してください・・・
商は減算した回数を数えれば良いですから、カウンタですね。
余りは元の数から減算を繰り返し、これ以上引くとマイナスになる、という数値です。
合計の逆で、変数「amri」に元の数「input1」を入れておいて、
amari -= input2; |
で、どんどん減算していきます。
繰り返し条件は、
while (amari >= input2) { |
となっていますので、
amariがinput2より小さくなったら、繰り返しを終了します。
※amariとinput2が同じ時は、まだ減算できます。
では、別の数値を入力してテストを行ってみましょう。
<実行結果>
元の数を入力してください:4 割る数を入力してください:5 商は0、余りは4です。 続行するには何かキーを押してください・・・
元の数より割る数を大きくしてみましたが、正しく結果が表示されました。
では「0」を使ってみましょう。
<実行結果>
元の数を入力してください:0 割る数を入力してください:5 商は0、余りは0です。 続行するには何かキーを押してください・・・
元の数を「0」にすると、正しく結果が出ています。
では、割る数に「0」を入れてみます。
<実行結果>
元の数を入力してください:5 割る数を入力してください:0
終わらなくなりました・・・
元の数から割る数を減算していきますが、「0」を減算していますから、いつまでたっても元の数が減らないのです。
では、応急処置を・・・と言いたい所ですが、「0」で割るというのは元々コンピュータでは出来ないのです。
下のプログラムを実行してみてください。
<sample program 044-02>
#include <stdio.h> int main(void) { int data; data = 10; printf("%d\n", data / 0); return 0; } |
<実行結果>
エラーになりました。
よく見ると、コンパイルした時に警告(warning)が出ています。
warning C4723: 除算の2番目のオペランドは、コンパイル時に 0 と評価され、不定の結果を返します。
「除算の2番目のオペランド」とは、除算の右辺のことです。
なぜ、このような警告が出るのか説明します。
ゼロ除算については、以前に少し書きました。
1÷0.1の答えはいくつでしょう?
「10」ですね。
1÷0.01は?
「100」です。
1÷0.001は?
「1000」です。
このまま、右辺をず〜っとゼロに近づけていくと、答えはどんどん大きくなっていきます。
つまり、ゼロで割ると答えが無限大となってしまい、コンピュータでは計算出来ないのです。
では、除算のプログラムに戻って、ゼロ除算を回避するプログラムを考えてみましょう。
解答例です。
<sample program 044-03>
#include <stdio.h> int main(void) { int input1; int input2; int syou; int amari; printf("元の数を入力してください:"); scanf("%d", &input1); printf("割る数を入力してください:"); scanf("%d", &input2); if (input2 != 0) { syou = 0; amari = input1; while (amari >= input2) { amari -= input2; syou++; } printf("商は%d、余りは%dです。\n", syou, amari); } else { printf("ゼロ除算エラー\n"); } return 0; } |
<実行結果>
元の数を入力してください:5 割る数を入力してください:0 ゼロ除算エラー 続行するには何かキーを押してください・・・
割る数(input2)が「0」の場合、計算をせず「ゼロ除算エラー」と表示します。
では、マイナスへの対処を考えてみましょう。
乗算では、右辺がマイナスの場合を考えればよかったのですが、除算の場合両辺とも考慮する必要があります。
−8÷4
−8から4を減算するとマイナスが増加していきます。
8÷−4
8から−4を減算するとどんどん増えていきます。
−8÷−4
−8から−4を減算すると2回で0になると思いますが、実際には繰り返し条件が、
amari = input1; while (amari >= input2) { |
となっているため、最初から繰り返し条件が不成立となり、一度も繰り返されずに終了します。
色々と効率の良い方法はありそうですが、前回の乗算で使った「minus_flag」を利用して考えてみてください。
解答例です。
<sample program 044-04>
#include <stdio.h> int main(void) { int input1; int input2; int syou; int amari; int left_minus_flag; int right_minus_flag; printf("元の数を入力してください:"); scanf("%d", &input1); left_minus_flag = 0; if (input1 < 0) { left_minus_flag = 1; input1 = -input1; } printf("割る数を入力してください:"); scanf("%d", &input2); right_minus_flag = 0; if (input2 < 0) { right_minus_flag = 1; input2 = -input2; } if (input2 != 0) { syou = 0; amari = input1; while (amari >= input2) { amari -= input2; syou++; } if (left_minus_flag == 1) { syou = -syou; } if (right_minus_flag == 1) { syou = -syou; } printf("商は%d、余りは%dです。\n", syou, amari); } else { printf("ゼロ除算エラー\n"); } return 0; } |
<実行結果1>
元の数を入力してください:-8 割る数を入力してください:4 商は-2、余りは0です。 続行するには何かキーを押してください・・・
<実行結果2>
元の数を入力してください:8 割る数を入力してください:-4 商は-2、余りは0です。 続行するには何かキーを押してください・・・
<実行結果3>
元の数を入力してください:-8 割る数を入力してください:-4 商は2、余りは0です。 続行するには何かキーを押してください・・・
右辺か左辺がマイナスの場合、商はマイナスになり、右辺も左辺もマイナスの場合、商はプラスになります。
では、次回は累乗(べき乗)を乗算の繰り返しで行うというプログラムを作ってみましょう。