閉じる

C言語の四則演算と剰余(+, -, *, /, %)基礎と使い方

C言語で計算を行う最初の一歩は、四則演算と剰余の理解です。

ここでは+, -, *, /, % の基本から、整数と浮動小数点の違い、演算子の優先順位、ありがちなエラーの回避法までを、サンプルコードと出力結果を添えて丁寧に解説します。

初心者の方でも段階的に読み進められるよう、意図が伝わる書き方と注意点をまとめました。

C言語の四則演算と剰余の基本 (+, -, *, /, %)

各演算子の意味と使い方

C言語の基本的な演算子は次の5つです。

式の左右にある値(オペランド)に対して演算を行い、新しい値を返します

左辺値に直接代入されるわけではない点に注意してください。

演算子と用途の一覧です。

演算子名前説明典型的な結果例
+加算3 + 52つの値を足します8
-減算9 - 2左から右を引きます7
*乗算4 * 6掛け算をします24
/除算7 / 3割り算をします整数同士は切り捨て(2)、どちらかが浮動小数点なら小数(2.333…)
%剰余(余り)7 % 3割り算の余りを求めます1

% は整数型に対してのみ使用できます

浮動小数点(float, double, long double)には使えません。

サンプルコード

まずは基本の使い方を実行してみます。

整数型の計算と結果の表示です。

C言語
#include <stdio.h>

int main(void) {
    // 変数の宣言と初期化
    int a = 7;
    int b = 3;

    // 四則演算と剰余
    int add = a + b;   // 加算
    int sub = a - b;   // 減算
    int mul = a * b;   // 乗算
    int div = a / b;   // 整数同士の除算は小数点以下が切り捨て
    int mod = a % b;   // 余り

    // 結果の表示
    printf("a = %d, b = %d\n", a, b);
    printf("a + b = %d\n", add);
    printf("a - b = %d\n", sub);
    printf("a * b = %d\n", mul);
    printf("a / b = %d\n", div);
    printf("a %% b = %d\n", mod); // % を出力するには %% と書く

    return 0;
}
実行結果
a = 7, b = 3
a + b = 10
a - b = 4
a * b = 21
a / b = 2
a % b = 1

整数の除算は小数を返さず、0方向へ切り捨てられることを最初に押さえましょう。

変数とリテラルで計算する

演算子は変数同士、変数とリテラル(定数)、リテラル同士のいずれにも使えます。

読みやすさのため、意味のある変数名と適切な型を選ぶと良いです。

C言語
#include <stdio.h>

int main(void) {
    int width = 5;        // 変数
    int height = 3;       // 変数
    int area = width * height;       // 変数同士
    int expanded = area + 10;        // 変数 + リテラル
    int border = (width + 2) * (height + 2); // 括弧で意図を明確に

    printf("area = %d\n", area);
    printf("expanded = %d\n", expanded);
    printf("border = %d\n", border);

    return 0;
}
実行結果
area = 15
expanded = 25
border = 35

型と計算結果の違い (整数演算/浮動小数点演算)

整数除算は0方向へ切り捨て (/)

C99以降、整数の除算は結果を0方向へ切り捨てます。

負の数を含む場合の挙動も確認しておきましょう。

C言語
#include <stdio.h>

int main(void) {
    printf("7 / 3 = %d\n", 7 / 3);     // 2
    printf("-7 / 3 = %d\n", -7 / 3);   // -2 (0方向へ切り捨て)
    printf("7 / -3 = %d\n", 7 / -3);   // -2
    printf("-7 / -3 = %d\n", -7 / -3); // 2
    return 0;
}
実行結果
7 / 3 = 2
-7 / 3 = -2
7 / -3 = -2
-7 / -3 = 2

浮動小数点の除算結果

片方でも浮動小数点なら、結果は浮動小数点になります。

出力のフォーマット指定子に注意します。

C言語
#include <stdio.h>

int main(void) {
    int a = 7, b = 3;
    double r1 = a / b;        // 整数同士で計算してから代入 → 2 が 2.000000 に
    double r2 = (double)a / b; // 片方をdoubleに → 2.333333...
    double r3 = 7.0 / 3;       // リテラルをdoubleに → 2.333333...

    printf("r1 = %f\n", r1);
    printf("r2 = %.6f\n", r2);
    printf("r3 = %.6f\n", r3);
    return 0;
}
実行結果
r1 = 2.000000
r2 = 2.333333
r3 = 2.333333

平均値や割合を計算するときは、必ず片方を浮動小数点にしてから割り算を行います。

剰余%は整数型のみ

% は整数型にしか使えません

浮動小数点で余りを求めたいなら、fmod(math.h)を使います。

C言語
// コンパイルエラーの例: 浮動小数点に % は使えない
// double x = 7.5;
// double y = 2.0;
// double r = x % y; // エラー

// 正しい方法 (fmod)
#include <stdio.h>
#include <math.h>

int main(void) {
    double x = 7.5, y = 2.0;
    double r = fmod(x, y); // 7.5 を 2.0 で割った余り: 1.5
    printf("fmod(%.1f, %.1f) = %.1f\n", x, y, r);
    return 0;
}
実行結果
fmod(7.5, 2.0) = 1.5

型変換とキャストで意図を明確に

必要なときにだけ明示的キャストで意図を示すと、整数除算の罠を避けられます。

C言語
#include <stdio.h>

int main(void) {
    int sum = 5 + 6 + 7;   // 18
    int count = 3;

    // 悪い例: 先に整数除算してからdoubleに代入 → 6.000000
    double avg_bad = sum / count;

    // 良い例: 片方をdoubleへ明示的キャストしてから除算 → 6.000000
    double avg_ok = (double)sum / count;

    printf("avg_bad = %.6f\n", avg_bad);
    printf("avg_ok  = %.6f\n", avg_ok);
    return 0;
}
実行結果
avg_bad = 6.000000
avg_ok  = 6.000000

この例では値が同じですが、sum や count が割り切れないときに差が出ます

たとえば sum=5, count=2 なら avg_bad は 2.000000、avg_ok は 2.500000 です。

通常算術変換とint昇格

Cの式評価では通常算術変換(usual arithmetic conversions)と整数昇格(integer promotions)が自動で行われ、結果型が決まります。

  • 概要
    • 整数昇格: charshort は式中で少なくとも int に昇格してから計算します。
    • 通常算術変換: 整数と浮動小数点を混在させると、より表現力の高い型(例: double)へ広がります。

代表的な規則(簡略版)をまとめます。

オペランドの型の組み合わせ結果の型の例ポイント
int と intint整数演算。/ は切り捨て
int と doubledoubleint が double に変換される
float と doubledoublefloat は double に拡張
short と intintshort は整数昇格で int に
unsigned と signedルールにより広い側へ場合によりunsigned側に引き上げ

実感するための短い例です。

C言語
#include <stdio.h>

int main(void) {
    char a = 100, b = 27;
    int s = a + b; // a, b は整数昇格され int で計算 → 127
    double d = 2 + 5.0; // 2 は double に変換 → 7.0
    
    printf("s = %d\n", s);
    printf("d = %.1f\n", d);
    return 0;
}
実行結果
s = 127
d = 7.0

符号ありと符号なしの混在は思わぬ結果を生みます。

型を合わせる、必要に応じて明示的キャストを使うなど、意図を示すことが大切です。

演算子の優先順位と括弧の使い方

*, /, % は +, – より優先

*、/、% は +、- よりも先に評価されます

意図しない順序で計算されないよう、結果が曖昧になり得る式には括弧を使います。

C言語
#include <stdio.h>

int main(void) {
    int r1 = 2 + 3 * 4;     // 3*4 が先 → 2 + 12 = 14
    int r2 = (2 + 3) * 4;   // 括弧が優先 → 5 * 4 = 20
    printf("r1 = %d, r2 = %d\n", r1, r2);
    return 0;
}
実行結果
r1 = 14, r2 = 20

同優先順位は左結合

同じ優先順位の演算子(例: /*)は左から右へ評価されます。

C言語
#include <stdio.h>

int main(void) {
    int r = 20 / 4 * 2; // (20 / 4) * 2 = 5 * 2 = 10
    printf("r = %d\n", r);
    return 0;
}
実行結果
r = 10

読みやすさ重視で括弧を使う

「他人が読んで一度で意図がわかるか」を基準に括弧を使うと保守性が上がります。

特に複数の演算子が混在する式や、単位が異なる値を混ぜる式では明示的に括弧でグループ化しましょう。

C言語
#include <stdio.h>

int main(void) {
    int base = 100, tax_percent = 10, discount = 15;
    // 税込み後に割引するのか、割引後に税をかけるのかで違いが出る
    int price_after_tax_then_discount = (base * (100 + tax_percent) / 100) - discount;
    int price_after_discount_then_tax = ((base - discount) * (100 + tax_percent) / 100);

    printf("tax→discount: %d\n", price_after_tax_then_discount);
    printf("discount→tax: %d\n", price_after_discount_then_tax);
    return 0;
}
実行結果
tax→discount: 95
discount→tax: 93

よくあるエラーと落とし穴の回避

ゼロ除算を防ぐ

0で割ると整数では未定義動作(クラッシュ等)になります。

浮動小数点では infnan が生じます。

割る前に必ず0チェックを行いましょう。

C言語
#include <stdio.h>

int main(void) {
    int x = 10, y = 0;

    if (y == 0) {
        printf("割り算できません(ゼロ除算)\n");
    } else {
        printf("x / y = %d\n", x / y);
    }

    double a = 1.0, b = 0.0;
    // 浮動小数点はゼロ除算で inf/nan になることがある
    if (b == 0.0) {
        printf("浮動小数点のゼロ除算は避けましょう\n");
    } else {
        printf("a / b = %f\n", a / b);
    }
    return 0;
}
実行結果
割り算できません(ゼロ除算)
浮動小数点のゼロ除算は避けましょう

オーバーフロー/アンダーフローに注意

符号付き整数のオーバーフローは未定義動作です。

事前に範囲をチェックするか、より広い型を使います。

C言語
#include <stdio.h>
#include <limits.h> // INT_MAX, LLONG_MAX

int main(void) {
    int a = INT_MAX - 5;
    int b = 10;

    // 加算の安全チェック(単純化した例)
    if (b > 0 && a > INT_MAX - b) {
        printf("オーバーフローの可能性があります\n");
    } else {
        printf("a + b = %d\n", a + b);
    }

    long long x = LLONG_MAX / 2;
    long long y = 3;

    if (y != 0 && x > LLONG_MAX / y) {
        printf("乗算でオーバーフローの可能性があります\n");
    } else {
        printf("x * y = %lld\n", x * y);
    }

    return 0;
}
実行結果
オーバーフローの可能性があります
乗算でオーバーフローの可能性があります

浮動小数点では「アンダーフロー(極小値へ丸め)」や「丸め誤差」が生じます。

必要に応じて doublelong double を使い、比較は許容誤差を設けます。

負の数と剰余%の符号

C99以降、剰余の符号は被除数(左オペランド)と同じです。

C言語
#include <stdio.h>

int main(void) {
    printf("-7 %% 3  = %d\n", -7 % 3);   // -1
    printf("7 %% -3  = %d\n", 7 % -3);   // 1
    printf("-7 %% -3 = %d\n", -7 % -3);  // -1
    return 0;
}
実行結果
-7 % 3  = -1
7 % -3  = 1
-7 % -3 = -1

1/2 と 1.0/2 の違い

整数同士の割り算は切り捨て、小数が混じれば小数計算になります。

C言語
#include <stdio.h>

int main(void) {
    printf("1 / 2   = %d\n", 1 / 2);     // 0
    printf("1.0 / 2 = %.1f\n", 1.0 / 2); // 0.5
    return 0;
}
実行結果
1 / 2   = 0
1.0 / 2 = 0.5

浮動小数点の精度誤差に注意

2進表現では0.1や0.2を正確に表せないため、0.1 + 0.2 が 0.3 と厳密には一致しません

比較には許容誤差(イプシロン)を用います。

C言語
#include <stdio.h>
#include <math.h>

int main(void) {
    double x = 0.1 + 0.2;
    double y = 0.3;
    double eps = 1e-12;

    printf("0.1 + 0.2 = %.17f\n", x);
    printf("0.3       = %.17f\n", y);
    if (fabs(x - y) < eps) {
        printf("ほぼ等しいとみなせます\n");
    } else {
        printf("一致しません\n");
    }
    return 0;
}
実行結果
0.1 + 0.2 = 0.30000000000000004
0.3       = 0.29999999999999999
ほぼ等しいとみなせます

金額や誤差が許されない分野では整数(最小単位で持つ)で扱う設計も有効です。

まとめ

四則演算と剰余は、C言語のあらゆるプログラムの土台です。

整数の除算は0方向へ切り捨て、%は整数限定、混在型では通常算術変換が働くという3点をまず押さえましょう。

さらに、優先順位は*, /, % が +, – より先、曖昧さは括弧で解消する、ゼロ除算やオーバーフローを事前に回避する、といった基本も重要です。

浮動小数点の誤差を理解し、必要に応じてキャストで意図を明確にすれば、初心者でも安全で読みやすい数式が書けるようになります。

この記事を書いた人
エーテリア編集部
エーテリア編集部

プログラミングの基礎をしっかり学びたい方向けに、C言語の基本文法から解説しています。ポインタやメモリ管理も少しずつ理解できるよう工夫しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!