四則計算と算術演算子

四則計算

四則計算とは、足し算、引き算、掛け算、割り算のことです。
(加算、減算、乗算、除算)
プログラミングでは頻繁に計算を行います。

計算の仕方は単純で、見た目にもわかりやすいですが、いくつか注意点があります。

まずは簡単なサンプルコードから。


#include <stdio.h>

int main()
{
    int kekka;
    kekka = 4 + 3 * 2 / 2;
    printf("計算結果: %d", kekka);
    getchar();
}
計算結果: 7

「+」と「-」は算数の時と同じですが、掛け算と割り算の記号は半角文字が存在しないため、別の記号が割り当てられています。
上のサンプルコードは「4 + 3 × 2 ÷ 2」と同じで、算数と同じように掛け算と割り算が先に計算されるので、計算結果は7になり、7が変数kekkaに代入されます。

+
値を加算する
-
値を減算する
*
値を乗算する
/
値を除算する

こういった何らかの計算や比較などに使われる記号を演算子といいます。
数学の計算に使われる演算子を特に算術演算子と呼びます。

感覚的にわかると思いますが、変数に値を代入する場合、「=」記号の右側の計算が先に行われ、その結果が左側の変数に代入されます。
=も演算子の一種で代入演算子といいます。

何かを計算したり、関数を実行したりして結果を得ることを式を評価すると呼びます。
代入処理は、代入演算子の右側の式を評価し、その結果を左側の変数に代入している、と言えます。

代入自体も評価をして「代入した結果」を得ることができます。


int kazu1, kazu2;
kazu1 = (kazu2 = 10);

「kazu2 = 10」という代入式を評価すると、変数kazu2に代入された値を得ることができます。
その値を変数kazu1にさらに代入しています。
つまり両方に「10」が代入されます。

上記は後ろ側を丸括弧で囲っていますが、丸括弧の中身は先に計算されます。
(詳しくは後述します)
今回は見た目に分かりやすくするために丸括弧を使用していますが、代入式が連続する場合は右側から順に処理が行われるので丸括弧はなくても同じです。


int kazu1, kazu2;
kazu1 = kazu2 = 10;

特殊な算術演算子

C言語の算術演算では、四則計算用の演算子以外にも特殊な演算子が用意されています。


#include <stdio.h>

int main()
{
    int kekka1;
    int kekka2;
    kekka1 = 4 * (3 - 2) + 4;
    kekka2 = 10 % 3;
    printf("結果1: %d\n", kekka1);
    printf("結果2: %d", kekka2);
    getchar();
}
結果1: 8
結果2: 1
()
計算の順序を変える
%
余り(剰余)を求める

丸括弧は算数でも使用する記号で、括弧内を先に計算するように順序を変更します。
算数で登場する中括弧({})や大括弧([])は使えません。
計算順序を入れ子にして変更したい場合は、単純に丸括弧で入れ子にします。


kekka1 = 4 * ((3 - 2) + 4);

「%」記号は左側の値を右側の値で除算した後の余りを求めます。
「10 ÷ 3」の余りは1なので、変数kekka2には1が代入されます。

変数同士の演算

計算は、変数同士でも行うことができます。


#include <stdio.h>

int main()
{
	int kekka1 = 3 + 5;
	int kekka2 = kekka1 - 6;
	int kekka3 = kekka1 + kekka2;

    printf("kekka1: %d\nkekka2: %d\nkekka3: %d",
        kekka1, kekka2, kekka3);
    getchar();
}
kekka1: 8
kekka2: 2
kekka3: 10

ちなみに、上のコードではprintf関数の引数の途中で改行しています。
そのまま横に並べても構いませんが、一行が横に長くなりすぎるとコードが読みづらくなるので、こういった書き方もできます。
ただし、文字列(ダブルクォーテーション)の途中で改行してはいけません。
長すぎる文字列を途中で改行することは可能ですが、それは別の項で説明します。

複合代入演算子

変数を含む計算の結果を同じ変数に代入しなおす場合は、以下のような書き方ができます。


#include <stdio.h>

int main()
{
    int kekka;
    kekka = 5;
    kekka += 3;
    printf("kekka: %d", kekka);
    getchar();
}

7行目、kekka += 3は「kekka = kekka + 3」と同じ意味になります。
この演算子を複合代入演算子といいます。

a += b
a = a + bと同じ
a -= b
a = a - bと同じ
a *= b
a = a * bと同じ
a /= b
a = a / bと同じ
a %= b
a = a % bと同じ

演算の順序

複合代入演算子の演算の順序には注意してください。
通常の代入と同じく、複合代入演算子は最後に演算されます。
足し算や引き算のみの式ならば気にする必要はありませんが、掛け算、割り算を含む式の場合は演算結果に影響します。


#include <stdio.h>

int main()
{
	int kazu1 = 5;
	int kazu2 = 5;

	kazu1 = kazu1 * 3 - 1;
	kazu2 *= 3 - 1;

	printf("kazu1: %d\n", kazu1);
	printf("kazu2: %d", kazu2);
	getchar();
}
kazu1: 14
kazu2: 10

インクリメント、デクリメント演算子

やや特殊な演算子に、インクリメント演算子デクリメント演算子があります。

++a
aの値を1増やす(前置インクリメント)
a++
aの値を1増やす(後置インクリメント)
--a
aの値を1減らす(前置デクリメント)
a--
aの値を1減らす(後置デクリメント)

これらは以下のように使います。


#include <stdio.h>

int main()
{
    int inc = 10;
    int dec = 10;
    inc++;
    dec--;
    
    printf("inc: %d\ndec: %d", inc, dec);    
    getchar();
}
inc: 11
dec: 9

a++++aはどちらも同じように見えますが、その式を評価したときに得られる値が異なります。


#include <stdio.h>

int main()
{
    int kazu1 = 10;
    int kazu2 = 10;
    int kekka1 = kazu1++;
    int kekka2 = ++kazu2;

    printf("kekka1: %d\nkekka2: %d", kekka1, kekka2);
    getchar();
}
kekka1: 10
kekka2: 11

どちらも「値が10の変数」の中身を1増やす処理です。
7行目は変数kekka1に値を代入してから変数kazu1の値が1増えます。
8行目は変数kazu2の値が1増えてから変数kekka2に値が代入されます。

つまりインクリメント(デクリメント)演算子が先に来る場合は、変数の中身を増減する処理を先に行い、その結果を返します。
変数名が先に来る場合は、先に変数の値を返してから変数の中身を増減させます。
変数から値を取り出す場合は評価のタイミングに気を付けましょう。

結果が小数になる計算

以下はやや余談的な話です。
ちょっとだけ話がややこしいので、今はあまり気にしなくても良いです。
詳しい解説は後のページで改めて行います。

いままではすべて整数値しか扱ってきませんでしたが、計算の結果が小数になることはよくあります。
そのような場合に、今まで通りに整数型(int)だけを使っていると思わぬ結果となります。


#include <stdio.h>

int main()
{
    int kekka;
    kekka = 10 / 4;
    printf("計算結果: %d", kekka);
    getchar();
}

「10 ÷ 4」の計算結果は「2.5」なので、2.5と表示されることが期待されます。
しかし結果は以下のようになります。

計算結果: 2

int型で扱えるのは整数の値だけです。
無理やり小数値を扱おうとすると、小数点以下が切り捨てられてしまいます。
その結果、「2.5」は「2」となってしまったのです。

正しい計算結果を得る方法はいくつかありますが、ここでは簡単な方法を説明します。


#include <stdio.h>

int main()
{
    double kekka;
    kekka = 10 / 4.0;
    printf("計算結果: %f", kekka);
    getchar();
}
計算結果: 2.500000

まず、変数をint型からdouble型に変更します。
double型は小数を含む数値を扱うことができるデータ型です。

次に、計算対象のどちらか一方に小数点を付けます。
C言語ではコード中に整数を書くと、それはint型として扱われるというルールがあります。

そして、整数同士を計算させると内部的にはint型同士で計算されます。
「int型 ÷ int型」の計算結果は、内部的に結果を変数に代入する前にint型として扱われます。
そのため、「10 / 4」は「2」となり、「2」をdouble型の変数に代入しても「2」にしかならないのです。

しかし、一方を小数点で書くとその値は内部的にdouble型として扱われます
そして、int型とdouble型の計算結果はdouble型として扱われます

つまり、「10 / 4.0」は「int型 ÷ double型」とみなされ、その計算結果はdouble型となります。
計算結果がdouble型なので、それをdouble型の変数に代入することで、変数kekkaには正しい計算結果を保存することができます。
仮に変数kekkaをint型のままにしていた場合、代入の時点で小数点以下が切り捨てられてしまいます。

このような、データ型を別のデータ型に変換すること型変換といいます。
これは別途詳しく解説するので、「データ型が異なる値(変数)同士の計算は注意」ということは頭に入れておきましょう。

printf関数で小数を表示する

最後にprintf関数で計算結果を表示するのですが、ここでも少し変更しなければならない箇所があります。
%dは整数型(10進数)を表示するための変換指定子なので、そのままではdouble型の変数の中身を正しく表示することができません。
小数点以下が切り捨てられるだけならまだしも、全く違う数値が表示されます。

double型変数を正しく表示するには、%d%fに変更します。
これでようやく正しい計算結果が画面に出力されるようになります。

「2.500000」と、不要なゼロがついてしまっていますが、計算結果自体は正しいです。
表示する桁数を減らすことは可能ですが、その説明はかなりややこしいものになるのでここでは説明しません。
(興味のある人はprintf関数を参照してください)

このページのまとめ

  • 「+」「-」「*」「/」が四則計算の基本的な演算子
  • 複合代入演算子やインクリメント/デクリメント演算子なども活用しよう
  • インクリメントとデクリメントは評価のタイミングに注意
  • 異なるデータ型同士の計算はデータ型が変わる