第1章 第3節 足して引いて掛けて割って


← 前に戻る | 次に進む →

ここまでで、とりあえず変数の宣言や表示は理解できました。でも、コンピュータを扱っているのですから計算ぐらいできないと困りますよね。そこで、この節ではC++での演算について説明します。

まずは、日常よく使う加減乗除の四則演算についてです。以下のプログラムを見てください。

List 1.8 四則演算の例

#include <iostream>
using namespace std;

int main()
{
    int a, b, c, d, e, f;

    a = 5;      // aに5を代入.
    b = a + 5;  // aに5を足し、それをbに代入.
    c = b - 2;  // bから2を引き、それをcに代入.
    d = c * 3;  // cに3を掛け、それをdに代入.
    e = d / 4;  // dを4で割り、それをeに代入.
    f = a * b + d / e;  // aとbを掛け、dをeで割り、その二つを足す.

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
    cout << "d = " << d << endl;
    cout << "e = " << e << endl;
    cout << "f = " << f << endl;

    return 0;
}


a = 5
b = 10
c = 8
d = 24
e = 6
f = 54

どれも難しい計算ではありませんね。ここで、最後の計算(f)を見ると、掛け算、割り算のほうが、足し算よりも先に行われていることがわかります。こんなことは小学生でも知っていることでしょう。C++でも計算する順序が演算子によってはっきりと区別されています。

以下の表に主な演算子の種類と優先順位について示します。これらは上から順に優先順位が高く、下に行くにつれ低くなります。同じ色に分けられた演算子は同じ優先順位です。[注3: すべての演算子についての表はこちら]

演算子 意味 使い方
++ 後置インクリメント 左辺値++
-- 後置デクリメント 左辺値--
++ 前置インクリメント ++左辺値
-- 前置デクリメント --左辺値
- 単項のマイナス -式
+ 単項のプラス +式
& アドレス取得 &左辺値
* 間接参照 *式
new 構築 new 型
delete 解体 delete ポインタ
* 乗算 式*式
/ 除算 式/式
% 剰余 式%式
+ 加算 式+式
- 減算 式-式
< より小さい 式<式
<= 以下 式<=式
> より大きい 式>式
>= 以上 式>=式
== 等しい 式==式
!= 等しくない 式!=式
&& 論理積 式&&式
|| 論理和 式||式
= 代入 左辺値=式

見慣れない演算子もありますね。ひとまずここでは、わかるものだけ見ていけば大丈夫です。乗算や代入などはいちいち説明しなくてわかると思いますし、もしよくわからないと感じても、使い始めてみればとっても簡単なことがわかるでしょう。

ではここで焼きイモ屋さんに楽をさせてあげるプログラムを作ってみましょう(^-^)。焼きイモの値段と個数を入れることで、消費税(5%)を入れた合計の金額を出すプログラムです。

おっと、その前に教えなくちゃいけないことが一つあります。それはキーボードからの入力です。画面への出力についてはストリームI/Oのcoutと出力演算子<<を使えばできることを以前にやりましたよね。それと同じように今度はcinと入力演算子>>を使えばよいのです。

それでは早速プログラムを見てみましょう。

List 1.9 焼きイモ屋のプログラム

#include <iostream>
using namespace std;

int main()
{
    int    price;  // 焼きイモ1個の値段.
    int    num;    // 焼きイモの個数.
    double tax;    // 消費税.
    double total;  // 合計額.

    tax = 0.05;    // 消費税は5%.

    cout << "焼きイモ1個の値段を入力してください: ";
    cin  >> price;
    cout << "焼きイモを何個買いますか? ";
    cin  >> num;

    total = (double)(price * num) * (1.0 + tax);

    cout << "買った焼きイモの合計額は消費税込みで "
         << (int)total << " 円です。" << endl;

    return 0;
}


焼きイモ1個の値段を入力してください: 350
焼きイモを何個買いますか? 3
買った焼きイモの合計額は消費税込みで 1102 円です。

まず、変数の宣言の部分を見てみましょう。焼きイモの値段(price)と個数(num)は小数になることはないので、intで宣言しています。消費税(tax)は5%つまり0.05となるのでdoubleで宣言します。そして、消費税込みの値段を考えて合計額(total)は小数点を扱えるようにdoubleにしました。

そして、numとpriceにcinを使って値を入力します。List 1.9の下の緑で示した数字が自分で入力した値になります(ここでは350と3)。

次に、合計額を求めるための計算です。あれ? 計算の中にもdouble型が書かれているよ。何で? と思われるかもしれませんが、これは式の値の型を別の型にキャスト(型変換)するためなんです。つまり、ここで使用されているpriceとnumはint型なので、その二つを使った式(price * num)もint型になります。しかし、taxはdouble型なので、それに合わせて(price * num)の型をint型からdouble型に変換したのです。これで、すべての計算においてdouble型に統一できました。そして、計算で求めた値はtotalに代入されます。

そして、最後に合計額を表示しますが、ここでまたキャストが出てきます。ここでは、totalをdouble型からint型に変換しているのです。これは、払う金額が小数点にならないように整数にするために行っています。因みに、double型をint型に変換した際は小数点は切り捨てられます。

さて、ここまでにいくつかキャストが出てきましたが、C++では、(型)式という形のキャスト方式とともにstatic_cast<型>(式)という形のキャスト方式も採用されています。そこで、List 1.9をこのキャスト方式を用いて書き換えてみると、以下のようになります。

List 1.10 焼きイモ屋のプログラム(static_cast版)

#include <iostream>
using namespace std;

int main()
{
    int    price;  // 焼きイモ1個の値段.
    int    num;    // 焼きイモの個数.
    double tax;    // 消費税.
    double total;  // 合計額.

    tax = 0.05;    // 消費税は5%.

    cout << "焼きイモ1個の値段を入力してください: ";
    cin  >> price;
    cout << "焼きイモを何個買いますか? ";
    cin  >> num;

    total = static_cast<double>(price * num) * (1.0 + tax);

    cout << "買った焼きイモの合計額は消費税込みで "
         << static_cast<int>(total) << " 円です。" << endl;

    return 0;
}


焼きイモ1個の値段を入力してください: 350
焼きイモを何個買いますか? 3
買った焼きイモの合計額は消費税込みで 1102 円です。

何でこんな面倒なことをしなくてはならないかと思われる人もいるかもしれませんが、キャストは非常に強力なもので、どんな型でも別の型に変更できてしまいます。そして、これはプログラムが読みにくくなったりバグが入り込みやすくなったりするのです。そこで、C++ではキャストを場合分けして使用することを奨励していて、その一つがstatic_castというわけです。このstatic_castはintからdoubleへの変換など、式に使われている型に基づいて変換します。

ここまで、キャストについていろいろと書いてきましたが、実はキャストはなるべくなら使用しないほうがよいのです。ええ! ここまでずっとキャストについて説明していたくせに! と思われるかもしれませんが、先ほども述べたとおり、キャストは暴力的ともいえる恐ろしいものなのです。キャストによって値は簡単に壊れ、しかもそれがさも正しいように振舞ったりします。この節ではキャストの便利な面と恐ろしい面を理解するためにわざとキャストを使用してみました。

では、整数と小数の両方が出てくるようなプログラムはどうすればよいのかと疑問に思われるかもしれませんが、その場合はすべてdouble型などのような浮動小数点型に統一するという手もあります。また、そのようにできない場合でも、できるだけstatic_castのようなC++方式のキャストを用いてわかりやすいプログラムにするように心がけることで、かなり改善されます。

暗黙の型変換について

この節で用いたプログラムでは、int型とdouble型が混在していた場合、すべてキャスト演算子を用いて型の変換をしていますが、実は明示的にキャスト演算子を使わなくても勝手に変換してくれるのです。これは暗黙の型変換と呼ばれるもので、可能ならばいつも情報を失わないように変換されます。しかし、以下のプログラムの場合はどうでしょうか。

int main()
{
    int a, b;
    double c;
    
    a = 3;  b = 2;
    c = a / b;
    cout << c << endl;
    
    return 0;
}

多くの人は3/2が計算されdouble型のcに代入されるのだから、1.5と表示されることを期待するでしょう。しかし、答えは1となります。つまり、int型であるaとbによる計算なので、その答えもint型の1となってしまうのです。

このように、暗黙の型変換に頼った異なる型同士の計算には、思わぬ落とし穴があるので気を付けましょう


← 前に戻る | 次に進む →


Copyright (C) Noriyuki Futatsugi/Foota Software, Japan.
All rights reserved.
d2VibWFzdGVyQGZ1dGF0c3VnaS5uZXQ=