浮動小数点数 解答ページ | Programming Place Plus 新C++編

トップページ新C++編浮動小数点数

このページの概要

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



解答・解説

問題1 (確認★)

次のプログラムがコンパイルエラーになる理由を説明してください。

#include <iostream>

int main()
{
    double double_value {2.0};
    int int_value {double_value};

    std::cout << double_value << "\n";
    std::cout << int_value << "\n";
}


コンパイルエラーになるのは、int_value を宣言しているところです。

初期値に double_value を指定していますが、これは double型の変数です。一方で、宣言したい変数 int_value は int型です。double型から int型へは自動的に変換が行われますが(暗黙の型変換)、情報の一部を失うかもしれません(たとえば、2.1 を int型に変換すると 2 になってしまい、0.1 が消えてしまいます)。このような変換は縮小変換と呼ばれます(本編解説)。

縮小変換自体はコンパイルエラーになるものではありませんが、{} を使った初期化を行うと、縮小変換を許可せず、コンパイルエラーになります。もし、int_value の宣言が、次のように書かれていたらコンパイルエラーにはなりません。

int int_value = double_value;  // OK. ただし小数点以下が切り捨てられる

問題2 (確認★)

次のそれぞれの式で、2つのオペランドは何型として扱われますか?

  1. 2.5 + 4.0
  2. 2.5 + 10
  3. true + 2.5
  4. ‘a’ + 2.5


ある演算子の2つのオペランドの型が、整数型と浮動小数点型だった場合、浮動小数点型のほうに合わせるように暗黙の型変換がおこなわれます(本編解説)。

true'a' も整数型の一種なので、これらも double型に変換されます(本編解説)。

そのため、問題の4つの式はどれも、「double型 + double型」の式になります。

問題3 (基本★)

商品の値段を入力すると、消費税込みの価格を出力するプログラムを作成してください。消費税率は 8% および 10% として、両方の場合を出力するようにしてください。


たとえば、次のように書けます。

#include <iostream>

int main()
{
    std::cout << "Please enter the price.\n";
    int price {};
    std::cin >> price;

    std::cout << "tax rate 8%: " << price * 1.08 << "\n";
    std::cout << "tax rate 10%: " << price * 1.1 << "\n";
}

実行結果:

Please enter the price.
2500  <-- 入力した内容
tax rate 8%: 2700
tax rate 10%: 2750

ここでは、価格は整数であるものとして int型で受け取りました(日本円ならそれで問題ないでしょう)。

あとは、消費税率 8% なら 1.08 を、10% なら 1.1 を乗算すれば、税込み価格が得られます。このときの計算は、「int型 * double型」になっており、問題2でみたとおり、2つのオペランドは double型として計算されていて、その計算結果も double型です。std::cout<< は、int型だろうと double型だろうと、そのまま受け取ってくれるので、特に気にすることはありません。

問題4 (基本★★)

1 を 2 で割った結果として 0.5 を得るには、どのようにコードを書けばいいですか?


1 も 2 も int型なので、そのまま 1 / 2 とすると、その結果は小数点以下が切り捨てられて 0 になってしまいます。0.5 を得るには、浮動小数点数として計算させればいいです。

1つの方法は、1.0 / 2.0 のように浮動小数点数リテラルで書くことです。

#include <iostream>

int main()
{
    std::cout << 1.0 / 2.0 << "\n";
}

実行結果:

0.5

演算子の2つのオペランドの一方が整数型、他方が浮動小数点型のとき、浮動小数点型のほうに合わせられるというルールがあるので(本編解説)、1.0 / 2 とか 1 / 2.0 のように片方だけを浮動小数点数リテラルにするのでも問題ありません。

#include <iostream>

int main()
{
    std::cout << 1.0 / 2 << "\n";
    std::cout << 1 / 2.0 << "\n";
}

実行結果:

0.5
0.5

また、static_cast を使って明示的に浮動小数点型にする手もあります(本編解説)。この場合も一方だけを double型にするのでも十分です。

#include <iostream>

int main()
{
    std::cout << static_cast<double>(1) / static_cast<double>(2) << "\n";
    std::cout << static_cast<double>(1) / 2 << "\n";
    std::cout << 1 / static_cast<double>(2) << "\n";
}

実行結果:

0.5
0.5
0.5

なお、次のように書くのは間違っています。

#include <iostream>

int main()
{
    std::cout << static_cast<double>(1 / 2) << "\n";
}

実行結果:

0

static_cast<double>(1 / 2) は、1 / 2 を計算した結果の値を double型に変換することになります。1 / 2 は int型による計算なので、この結果は int型の 0 です。それを double型に変換しても、double型の 0.0 が得られるだけです。

問題5 (応用★★)

double型から int型の暗黙の型変換では、小数点以下が捨てられますが、四捨五入にしたい場合はどうすればいいでしょうか?


暗黙の型変換のルール自体は、C++ の仕様として定められているものなので、どうしようもありません。このルールの中でうまく工夫する必要があります。

まず、四捨五入です。たとえば、3.03.4 なら 3 に、3.53.9 なら 4 にしたいということです。3.53.9 のときに 4 にできるかどうかが問題ですが、小数点以下を切り捨てられた結果が 4 になればいいので、3.53.9 を 4以上の値になるようにすればいいということになります。逆に、3.03.4 の方はそもそも正しい結果が得られているので、これを壊してはいけません。そう考えると、切り捨てられてしまう前に 0.5 を加算してやればいいことが分かります。

#include <iostream>

int main()
{
    int result {};

    result = static_cast<int>(3.0 + 0.5);
    std::cout << result << "\n";

    result = static_cast<int>(3.5 + 0.5);
    std::cout << result << "\n";
}

実行結果:

3
4

【上級】標準ライブラリに、四捨五入をおこなう std::round関数があります。1


参考リンク



更新履歴




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