C言語で余りを求める%演算子の使い方【剰余】

394, 2022-01-21

目次

C言語で余りを求める%演算子の使い方

C言語にはいくつも演算子がありますが、その中に割り算の余りを求める演算子があります。
これは剰余演算子%演算子)と呼ばれています。
この演算子を使うと割り算の余りを求めることが可能です。

この記事ではこの剰余演算子の使い方を具体的に解説します。

関連記事

%演算子を使う

割り算の余りを求める%演算子は普通の足し算の演算子+や引き算の演算子-と同じように使うことができます。
↓がサンプルコードです。

#include <stdio.h>

int main(void) {
    int result = 5 % 3;  // 5を3で割った余りを求める

    printf("%d\n", result);
    // 2

    return 0;
}

5 % 3という演算は「53で割ってその余りを求める」という演算です。
53で割った余りは2になるので、↑のコードのresult変数には2が保存されます。
このように%演算子を使うと割り算の余りを求めることが可能です。

%演算子の特徴

%演算子は割り算の余りを求めるのですが、この特性について解説します。
%演算子で演算を行うと、左辺の値が右辺の値の範囲内に収まります
たとえば左辺が100で右辺が10だったら、その演算の結果は0から9の間になります。
これは左辺がどれだけ大きくなっても同じです。
つまり%演算子を使うことで、大きな値を循環性を持った特定の値に狭めることが出来るということになります。

%演算子の結果は循環性を持っています。
↓の計算表をご覧ください。

0 % 3 ... 0
1 % 3 ... 1
2 % 3 ... 2
3 % 3 ... 0
4 % 3 ... 1
5 % 3 ... 2
6 % 3 ... 0
...

%演算子の右辺は3で固定です。
左辺は0から6まで増えています。
その計算結果を見ると、0, 1, 2, 0, 1, 2, ...と循環しているのがわかります。
このように剰余を求めると特定の値を特定の範囲内で循環させることが可能になります。

0除算エラー

%演算子は「割り算」の余りを求めます。
そのため普通の割り算と同様に右辺に0を使うことはできません

#include <stdio.h>

int main(void) {
    printf("%d\n", 10 % 0);
    return 0;
}

GCCでは%演算子の右辺に0を使うと↓のように警告が出力されます。

$ gcc err.c
err.c: In function ‘main’:
err.c:4:23: warning: division by zero [-Wdiv-by-zero]
    4 |     printf("%d\n", 10 % 0);
      |                       ^

プログラムを実行すると↓のように例外が送出されます。

$ ./a.out
Floating point exception

%演算子の右辺に0を使うとこのようにプログラムがクラッシュする場合があります
ですので%演算子を使う場合は右辺が0になっていないか注意する必要があります。

割り算で0を使えない理由ですが、これは数学的に演算が定義できないため使うことができないからです。
数学は定義の連続で成り立っている学問ですが、0除算はその定義ができないので演算することもできないんですね。

(^ _ ^)

0はアナーキー

(・ v ・)

おそろしや

いろいろな%演算

%演算子でいろいろ計算してみましょう。

#include <stdio.h>

int main(void) {
    int result;

    result = 10 % 2;
    printf("10 % 2 = %d\n", result);
    // 10 % 2 = 0

    result = 9 % 2;
    printf("9 % 2 = %d\n", result);
    // 9 % 2 = 1

    result = 14 % 3;
    printf("14 % 3 = %d\n", result);
    // 14 % 3 = 2

    result = 1234 % 23;
    printf("1234 % 23 = %d\n", result);
    // 1234 % 23 = 15

    return 0;
}

%演算子を使ったテクニック

%演算子はその結果が循環するという特徴があります。
つまり値の範囲を絞りたい場合に使えるということなんですが、これを利用して添え字のバッファーオーバーフローを防ぐことが出来ます

#include <stdio.h>

enum {
    ARRAY_SIZE = 5,
};

int main(void) {
    int ary[ARRAY_SIZE] = {0, 1, 2, 3, 4};  // 配列
    int index = 10;  // 添え字
    int elem = ary[index % ARRAY_SIZE];  // 添え字を配列のサイズで剰余する

    printf("%d\n", elem);
    // 0

    return 0;
}

↑のコードでは、配列aryを添え字indexで参照しています。
しかしindexの値は10なのに、配列のサイズは5になっています。
このままだと配列のサイズを超えた添え字でアクセスしてしまうことになります。
このような配列の範囲外のアクセスはプログラムがクラッシュする場合もあるため、厄介なバグになります。

そこでindex % ARRAY_SIZEとやってindexARRAY_SIZEで剰余します。
こうするとindex値がARRAY_SIZEの範囲で循環します
循環するということはつまり添え字が配列の範囲外を飛び越える心配が無いということです。

↑のコードをコンパイルして実行すると何事もなく実行されます。

このように配列の添え字を%演算子で演算子しておくと、厄介なバグを減らすことができます。
このテクニックは添え字の値が未知的な場合に使うことができます。

ただし注意点として、%演算子は割り算の仲間なので、けっこう処理が重いということです。
そのため何でもかんでも配列の添え字で%演算子を使っているとプログラムの動作に影響が出る場合もあります。
ゲームや速度が必要なプログラムなどではその点に注意して使ってください。

%=演算子の使い方

%=という剰余代入演算子があります。
これを使うと短い式で演算を行うことができます。

#include <stdio.h>

int main(void) {
    int a = 10;

    a %= 3;

    printf("%d\n", a);
    // 1

    return 0;
}

↑のa %= 3という式はa = a % 3と同じ結果になります。
そのためaには103で割った余りの1が保存されます。

おわりに

今回は%演算子の使い方を解説しました。
%演算子は非常にパワフルな演算子で、便利に使うことができます。
マスターして使えるようになっておきましょう。

(^ _ ^)

割った余りは使い勝手が良い

(・ v ・)

良い



この記事のアンケートを送信する