計算の仕方 解答ページ | Programming Place Plus C言語編 第3章

トップページC言語編第3章

問題①

問題① 次のプログラムの実行結果はどうなりますか?

#include <stdio.h>

int main(void)
{
    printf("%d\n", 3 + 3 * 3);
    printf("%d\n", 3 + 3 / 3);
    printf("%d\n", 3 + 3 % 3);
}


乗算、除算、剰余の計算は、加算よりも先に行われます。

3 + 3 * 3 は、3 * 3 が先に計算されて 9。3 + 9 になるので最終結果は 12 です。

3 + 3 / 3 は、3 / 3 が先に計算されて 1。3 + 1 になるので最終結果は 4 です。

3 + 3 % 3 は、3 % 3 が先に計算されて 0。3 + 0 になるので最終結果は 3 です。

よって、実行結果は以下のようになります。

12
4
3

問題②

問題② 次のプログラムの実行結果はどうなりますか?

#include <stdio.h>

int main(void)
{
    printf("%d\n", 3 / 1);
    printf("%d\n", 3 / 2);
    printf("%d\n", 3 / 3);
    printf("%d\n", 3 / 4);
    printf("%d\n", 3 / -1);
    printf("%d\n", 3 / -2);
    printf("%d\n", 3 / -3);
    printf("%d\n", 3 / -4);
}


整数の除算をした結果、小数点以下の部分があったら、それは無視されます。ですから、3 / 2 は 1.5 ではなく 1 になりますし、3 / 4 は 0.75 ではなく 0 になります。

負数が入った場合も考え方は同様です。3 / -2 は -1.5 ですが、小数点以下を無視して -1 になります。3 / -4 は -0.75 ですから -0 であり、つまりは 0 です。

実行結果は次のようになります。

3
1
1
0
-3
-1
-1
0

問題③

問題③ 次のプログラムの実行結果はどうなりますか?

#include <stdio.h>

int main(void)
{
    printf("%d\n", 3 % 1);
    printf("%d\n", 3 % 2);
    printf("%d\n", 3 % 3);
    printf("%d\n", 3 % 4);
    printf("%d\n", 3 % -1);
    printf("%d\n", 3 % -2);
    printf("%d\n", 3 % -3);
    printf("%d\n", 3 % -4);
}


% は剰余の計算です。余りが出ない場合の結果は 0 になります。

また、符号については、左オペランドの符号に合わせられるというルールです。そのため、このプログラムに登場する剰余の式の計算結果はすべて正の数になります。

実行結果は次のようになります。

0
1
0
3
0
1
0
3

「1 で割った余り」が少し混乱するかもしれません。計算した結果出てくる “余り” が、割る数(1) 以上になることはあり得ない(それなら余っていないので)ということを考えてみると分かりやすいかもしれません。1 で割った余りは 0 にしかなりません。

問題④

問題④ 3 + 5 の計算結果と、2 + 4 の計算結果を掛け合わせた結果を出力するプログラムを作成してください。


3 + 5 の計算結果は 8、2 + 4 の計算結果は 6 ですから、求めたい結果は 8 * 6 の 48 です。

単に、3 + 5 * 2 + 4 のように書いてしまうと、乗算が先に計算されますから、目的の結果を得られません。

それぞれの式を ( ) で囲んで、その内側が先に計算されるようにします。

#include <stdio.h>

int main(void)
{
    printf("%d\n", (3 + 5) * (2 + 4));
}

実行結果:

48

問題⑤

問題⑤ 次のプログラムの中で、問題がある行をすべて挙げてください。

#include <stdio.h>

int main(void)
{
    printf("%d\n", 3 / 0);
    printf("%d\n", 0 / 1);
    printf("%d\n", 3 % 0);
    printf("%d\n", 0 % 1);
    printf("%d\n", 1 / 0 + 1);
    printf("%d\n", 1 / (0 + 1));
    printf("%d\n", 1 / (3 % 2));
    printf("%d\n", 1 / (3 % 3));
}


このプログラムに潜んでいる問題とは、整数のゼロ除算です。除算演算子でも剰余演算子でも、右オペランドが 0 のときは未定義動作であり、そのようなプログラムを書いてはいけません。

まず、3 / 03 % 0 と書いてある行は問題ありです。

左オペランドは 0 でも構わないので、0 / 10 % 1 は問題ありません。

1 / 0 + 1 は問題があります。加算よりも除算のほうが先に計算されるので、まず 1 / 0 を計算しようとしますが、ここが未定義動作になります。

一方で、1 / (0 + 1) は問題ありません。括弧内が先に計算されますから、まず 0 + 1 が計算されて 1 になり、続いて 1 / 1 という計算を行うことになります。ゼロ除算はありません。

1 / (3 % 2)3 % 2 が 1 になるので、1 / 1 という計算をすることになり、やはり問題ありません。

1 / (3 % 3) は、3 % 3 の計算結果が 0 ですから、1 / 0 になってしまい、ゼロ除算をしていますから、この行には問題があります。

よって、問題がある行は、以下のとおりです。

問題⑥

10 / 3 の計算結果は 3 に、10 / 4 なら 2 になりますが、これは小数点以下が切り捨てられているということです。小数点以下を切り上げることを望むのなら、どのようにプログラムを書けばよいでしょうか?


小数点以下を切り上げたいということは、10 / 3 なら 3.333・・・を切り上げて 4。10 / 4 なら 2.5 を切り上げて 3 にしたいということです。

とはいえ、小数点以下を捨てるというC言語のルールを変えることはできませんから、工夫をこらす必要があります。

3.333 を 4.xxx のような 4以上の数になるように調整すれば、切り捨てのルールによって 4 を得られます。同様に、2.5 ではなく 3.x のような数にすれば、切り捨てられて 3 が得られます。

これを実現するには、事前に左オペランドに、「右オペランド - 1」を足しておきます。10 / 3 なら (10 + 3 - 1) / 3 にするということです。この式は 12 / 3 で 4 が得られます。10 / 4 なら (10 + 4 - 1) / 4 です。こちらは 13 / 4 で 3.25 になりますが、小数点以下が切り捨てられて 3 になります。

#include <stdio.h>

int main(void)
{
    printf("%d\n", (10 + 3 - 1) / 3);
    printf("%d\n", (10 + 4 - 1) / 4);
}

実行結果:

4
3


参考リンク


更新履歴



第3章のメインページへ

C言語編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る