乗算と除算 解答ページ | Programming Place Plus 新C++編

トップページ新C++編乗算と除算

このページの概要

このページは、練習問題の解答例や解説のページです。



解答・解説

問題1 (確認★)

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

#include <iostream>

int main()
{
    std::cout << 3 + 3 * 3 << "\n";
    std::cout << 3 + 3 / 3 << "\n";
    std::cout << 3 + 3 % 3 << "\n";
}


乗算、除算、剰余の計算は、加算よりも先に行われます(本編解説)。

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

問題2 (確認★)

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

#include <iostream>

int main()
{
    std::cout << 3 / 1 << "\n";
    std::cout << 3 / 2 << "\n";
    std::cout << 3 / 3 << "\n";
    std::cout << 3 / 4 << "\n";
    std::cout << 3 / -1 << "\n";
    std::cout << 3 / -2 << "\n";
    std::cout << 3 / -3 << "\n";
    std::cout << 3 / -4 << "\n";
}


整数の除算をした結果、小数点以下の部分があったら、それは無視されます(本編解説)。ですから、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

問題3 (確認★)

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

#include <iostream>

int main()
{
    std::cout << 3 % 1 << "\n";
    std::cout << 3 % 2 << "\n";
    std::cout << 3 % 3 << "\n";
    std::cout << 3 % 4 << "\n";
    std::cout << 3 % -1 << "\n";
    std::cout << 3 % -2 << "\n";
    std::cout << 3 % -3 << "\n";
    std::cout << 3 % -4 << "\n";
}


% は剰余の計算です。余りが出ない場合の結果は 0 になります(本編解説)。

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

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

0
1
0
3
0
1
0
3

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

問題4 (確認★)

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


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

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

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

#include <iostream>

int main()
{
    std::cout << (3 + 5) * (2 + 4) << "\n";
}

実行結果:

48

問題5 (確認★★)

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

#include <iostream>

int main()
{
    std::cout << 3 / 0 << "\n";
    std::cout << 0 / 1 << "\n";
    std::cout << 3 % 0 << "\n";
    std::cout << 0 % 1 << "\n";
    std::cout << 1 / 0 + 1 << "\n";
    std::cout << 1 / (0 + 1) << "\n";
    std::cout << 1 / (3 % 2) << "\n";
    std::cout << 1 / (3 % 3) << "\n";
}


このプログラムに潜んでいる問題とは、整数のゼロ除算です。除算演算子でも剰余演算子でも、右オペランドが 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 になってしまい、ゼロ除算をしていますから、この行には問題があります。

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

問題6 (応用★★★)

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 <iostream>

int main()
{
    std::cout << (10 + 3 - 1) / 3 << "\n";
    std::cout << (10 + 4 - 1) / 4 << "\n";
}

実行結果:

4
3


参考リンク



更新履歴




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