C#の剰余演算子「%」とは?余りの求め方・負の数・よくあるエラーを初心者向けに解説
はじめに
C#で「余り」を求めたいときに使うのが、剰余演算子の % です。
たとえば、10 を 3 で割ると、商は 3、余りは 1 になります。この「余りの 1」を求めるために使うのが、C#の剰余演算子です。
C#Console.WriteLine(10 % 3); // 1
% は、偶数・奇数の判定、倍数チェック、配列の添字を循環させる処理、時間の変換、ゲームやUIの周期処理など、実際のプログラミングでもよく使われます。
一方で、C#の剰余演算子には初心者がつまずきやすいポイントもあります。特に、負の数を扱ったときの結果、0で割ったときのエラー、小数で使う場合の丸め誤差などは注意が必要です。
この記事では、「C# 剰余」を初めて学ぶ人向けに、% の基本的な意味から、実践例、負の数の扱い、よくあるエラー、Math.DivRem の使い方まで順番に解説します。
1. C#の剰余演算子「%」とは?
1-1. 剰余演算子「%」は割り算の余りを求める演算子
C#の剰余演算子 % は、割り算をしたときの「余り」を求める演算子です。MicrosoftのC#リファレンスでも、% は左側の値を右側の値で割った後の余りを計算する演算子として説明されています。
たとえば、次のコードを見てください。
C#Console.WriteLine(10 % 3);
10 ÷ 3 は、商が 3、余りが 1 です。そのため、実行結果は次のようになります。
1
つまり、10 % 3 は「10を3で割った余り」を意味します。
1-2. 「剰余」「余り」「mod」「モジュロ」の違い
プログラミングを学んでいると、「剰余」「余り」「mod」「モジュロ」という言葉を見かけることがあります。
初心者のうちは、まず次のように理解しておけば問題ありません。
「余り」は、割り算をしたときに残る数です。
10 ÷ 3 = 3 余り 1
「剰余」は、プログラミングや数学で使われる少し正式な言い方です。C#の % は「剰余演算子」と呼ばれます。
「mod」や「モジュロ」は、数学や他のプログラミング言語で使われることが多い表現です。たとえば「10 mod 3 = 1」のように書くことがあります。
ただし、C#の % と数学的なmodは、負の数を扱うときに結果が異なる場合があります。この点は後の「負の数」の章で詳しく解説します。
1-3. C#での基本構文:a % b の意味
C#の剰余演算子は、次のように書きます。
C#a % b
これは、「a を b で割った余り」を意味します。
C#int result = 10 % 3;
Console.WriteLine(result); // 1
この場合、左側の 10 が割られる数、右側の 3 が割る数です。
10 % 3
を日本語で読むなら、
10を3で割った余り
です。
右側の値、つまり割る数が 0 になるとエラーの原因になるため、実際のコードでは注意が必要です。
1-4. まず覚えるべき計算例:10 % 3 は 1
剰余演算子を理解するために、まずは次の例を覚えましょう。
C#Console.WriteLine(10 % 3); // 1
なぜ 1 になるのかを、割り算で考えてみます。
10 ÷ 3 = 3 余り 1
3 × 3 = 9 で、10 から 9 を引くと 1 が残ります。
10 - 9 = 1
そのため、10 % 3 の結果は 1 です。
ほかにも、次のような計算があります。
C#Console.WriteLine(8 % 2); // 0
Console.WriteLine(9 % 2); // 1
Console.WriteLine(15 % 4); // 3
Console.WriteLine(20 % 5); // 0
余りが 0 になる場合は、「割り切れる」という意味になります。
2. C#で余りを求める基本的な使い方
2-1. int型で余りを求めるサンプルコード
C#で整数の余りを求める場合、まずは int 型で考えるとわかりやすいです。
C#int result = 10 % 3;
Console.WriteLine(result);
実行結果は次の通りです。
1
int は整数を扱う型です。剰余演算子 % は整数同士の計算でよく使われます。
もう少し例を見てみましょう。
C#int a = 17;
int b = 5;
int remainder = a % b;
Console.WriteLine(remainder); // 2
17 ÷ 5 は、商が 3、余りが 2 です。そのため、17 % 5 は 2 になります。
2-2. 変数を使って剰余を計算する方法
実際のプログラムでは、直接 10 % 3 と書くだけでなく、変数を使って剰余を計算することが多いです。
C#int number = 25;
int divisor = 4;
int remainder = number % divisor;
Console.WriteLine(remainder);
実行結果は次のようになります。
1
25 ÷ 4 は、商が 6、余りが 1 です。
変数名をわかりやすくすると、コードの意味も読み取りやすくなります。
C#int totalItems = 23;
int itemsPerPage = 5;
int remainingItems = totalItems % itemsPerPage;
Console.WriteLine(remainingItems); // 3
このコードでは、「23個のアイテムを1ページ5個ずつ表示したときに、最後のページに余るアイテム数」を求めています。
2-3. Console.WriteLineで結果を確認する
初心者がC#の剰余演算子を学ぶときは、Console.WriteLine を使って結果を確認するのがおすすめです。
C#Console.WriteLine(10 % 3);
Console.WriteLine(12 % 5);
Console.WriteLine(20 % 4);
Console.WriteLine(7 % 2);
実行結果は次のようになります。
1
2
0
1
それぞれの意味は次の通りです。
10 ÷ 3 = 3 余り 1
12 ÷ 5 = 2 余り 2
20 ÷ 4 = 5 余り 0
7 ÷ 2 = 3 余り 1
剰余演算子は、コードを読んだだけでは慣れるまで少しわかりにくい場合があります。最初のうちは、実際に出力して結果を確認しながら覚えると理解しやすくなります。
2-4. 「/」除算演算子と「%」剰余演算子の違い
C#では、割り算に関係する演算子として / と % があります。
/ は商を求める演算子です。
C#Console.WriteLine(10 / 3); // 3
% は余りを求める演算子です。
C#Console.WriteLine(10 % 3); // 1
10 ÷ 3 を考えると、商は 3、余りは 1 です。
10 ÷ 3 = 3 余り 1
そのため、C#では次のようになります。
C#Console.WriteLine(10 / 3); // 商: 3
Console.WriteLine(10 % 3); // 余り: 1
整数同士を / で割った場合、C#では結果も整数になり、小数部分は切り捨てられます。C#リファレンスでは、整数型の / の結果は整数型で、商は0方向に丸められると説明されています。
2-5. 商と余りをセットで理解する
剰余演算子 % は、/ とセットで理解するとわかりやすくなります。
C#int a = 10;
int b = 3;
int quotient = a / b;
int remainder = a % b;
Console.WriteLine($"商: {quotient}");
Console.WriteLine($"余り: {remainder}");
実行結果は次の通りです。
商: 3
余り: 1
この関係は、次の式で表せます。
a = b × 商 + 余り
今回の例では、次のようになります。
10 = 3 × 3 + 1
C#の剰余演算子を理解するうえで、この「商と余りの関係」はとても重要です。
3. C#の剰余演算子でよく使う実践例
3-1. 偶数・奇数を判定する:num % 2
C#の剰余演算子で最もよく使われる例のひとつが、偶数・奇数の判定です。
整数を 2 で割ったとき、余りが 0 なら偶数、余りが 1 なら奇数です。
C#int num = 8;
if (num % 2 == 0)
{
Console.WriteLine("偶数です");
}
else
{
Console.WriteLine("奇数です");
}
実行結果は次のようになります。
偶数です
8 % 2 は 0 なので、8 は偶数です。
奇数の場合も見てみましょう。
C#int num = 7;
if (num % 2 == 0)
{
Console.WriteLine("偶数です");
}
else
{
Console.WriteLine("奇数です");
}
実行結果は次の通りです。
奇数です
7 % 2 は 1 なので、7 は奇数です。
3-2. 倍数を判定する:num % 3 == 0
剰余演算子は、ある数が別の数の倍数かどうかを判定するときにも便利です。
たとえば、num が 3 の倍数かどうかを調べるには、次のように書きます。
C#int num = 15;
if (num % 3 == 0)
{
Console.WriteLine("3の倍数です");
}
else
{
Console.WriteLine("3の倍数ではありません");
}
実行結果は次のようになります。
3の倍数です
15 ÷ 3 は割り切れるため、15 % 3 は 0 です。
この考え方は、5 の倍数や 10 の倍数の判定にも使えます。
C#int num = 40;
if (num % 5 == 0)
{
Console.WriteLine("5の倍数です");
}
if (num % 10 == 0)
{
Console.WriteLine("10の倍数です");
}
余りが 0 なら割り切れる、つまり倍数であると判断できます。
3-3. 配列やListの添字を循環させる
剰余演算子は、配列や List の添字を循環させる処理にもよく使われます。
たとえば、次のような配列があるとします。
C#string[] colors = { "赤", "青", "緑" };
添字は次のようになります。
colors[0] = 赤
colors[1] = 青
colors[2] = 緑
この配列を、0, 1, 2, 0, 1, 2... のように繰り返し参照したい場合、% が便利です。
C#string[] colors = { "赤", "青", "緑" };
for (int i = 0; i < 10; i++)
{
int index = i % colors.Length;
Console.WriteLine(colors[index]);
}
実行結果は次のようになります。
赤
青
緑
赤
青
緑
赤
青
緑
赤
colors.Length は 3 です。i % 3 の結果は、常に 0、1、2 のいずれかになります。
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
この性質を使うと、配列の範囲内で添字を循環させることができます。
3-4. 時間・分・秒の変換で余りを使う
秒数を「分」と「秒」に分けるときにも、剰余演算子が役立ちます。
たとえば、125 秒を分と秒に変換してみましょう。
C#int totalSeconds = 125;
int minutes = totalSeconds / 60;
int seconds = totalSeconds % 60;
Console.WriteLine($"{minutes}分{seconds}秒");
実行結果は次の通りです。
2分5秒
125 ÷ 60 は、商が 2、余りが 5 です。
125秒 = 2分 5秒
/ で分を求め、% で余った秒を求めています。
もう少し発展させると、時・分・秒にも変換できます。
C#int totalSeconds = 3665;
int hours = totalSeconds / 3600;
int minutes = (totalSeconds % 3600) / 60;
int seconds = totalSeconds % 60;
Console.WriteLine($"{hours}時間{minutes}分{seconds}秒");
実行結果は次のようになります。
1時間1分5秒
時間変換では、割り算と剰余を組み合わせるとスッキリ書けます。
3-5. ループ処理で一定回数ごとに処理を分ける
剰余演算子は、ループの中で「一定回数ごとに処理を行う」ときにも使えます。
たとえば、1から10まで表示し、3回ごとにメッセージを出す例です。
C#for (int i = 1; i <= 10; i++)
{
Console.WriteLine(i);
if (i % 3 == 0)
{
Console.WriteLine("3回ごとの処理です");
}
}
実行結果は次のようになります。
1
2
3
3回ごとの処理です
4
5
6
3回ごとの処理です
7
8
9
3回ごとの処理です
10
i % 3 == 0 は、i が 3 の倍数のときに true になります。
このような処理は、ログ出力、進捗表示、ページ区切り、一定間隔での更新処理などに使えます。
3-6. ゲームやUIで周期的な処理を実装する
ゲームやUIでは、一定の周期で処理を切り替えたい場面があります。
たとえば、キャラクターのアニメーション画像を順番に切り替える場合を考えます。
C#string[] frames = { "frame1", "frame2", "frame3", "frame4" };
for (int count = 0; count < 10; count++)
{
int frameIndex = count % frames.Length;
Console.WriteLine(frames[frameIndex]);
}
実行結果は次のようになります。
frame1
frame2
frame3
frame4
frame1
frame2
frame3
frame4
frame1
frame2
count % frames.Length を使うことで、添字が 0 から 3 の範囲で繰り返されます。
この考え方は、次のような場面でも使えます。
アニメーションフレームの切り替え、カルーセル表示、背景色の繰り返し、ターン制ゲームのプレイヤー切り替え、一定フレームごとの処理などです。
C#int playerCount = 4;
for (int turn = 0; turn < 10; turn++)
{
int currentPlayer = turn % playerCount;
Console.WriteLine($"現在のプレイヤー: {currentPlayer}");
}
剰余演算子を使うと、「順番に回す」「一定周期で繰り返す」という処理を簡単に表現できます。
4. C#で負の数に剰余演算子「%」を使うとどうなる?
4-1. C#では余りの符号は左側の値に合わせられる
C#の剰余演算子で特に注意したいのが、負の数を扱う場合です。
C#では、整数の a % b の結果は a - (a / b) * b によって求められ、余りが 0 でない場合、その符号は左側の値に一致します。
つまり、次のようになります。
C#Console.WriteLine(5 % 4); // 1
Console.WriteLine(-5 % 4); // -1
-5 % 4 の結果は 1 ではなく -1 です。
ここを勘違いすると、配列の添字計算や循環処理でバグの原因になります。
4-2. 5 % 4、5 % -4、-5 % 4、-5 % -4 の違い
C#では、次の4つの計算結果を覚えておくと、負の数の剰余を理解しやすくなります。
C#Console.WriteLine(5 % 4); // 1
Console.WriteLine(5 % -4); // 1
Console.WriteLine(-5 % 4); // -1
Console.WriteLine(-5 % -4); // -1
結果を表にすると、次のようになります。
| 式 | 結果 |
|---|---|
5 % 4 | 1 |
5 % -4 | 1 |
-5 % 4 | -1 |
-5 % -4 | -1 |
注目すべきポイントは、右側の値ではなく、左側の値の符号に結果が影響されることです。
C#5 % -4 // 左側が正なので結果は 1
-5 % 4 // 左側が負なので結果は -1
C#で負の数に % を使うときは、「余りの符号は左側に合わせられる」と覚えておくとよいでしょう。
4-3. 数学のmodとC#の%は必ずしも同じではない
数学で使われるmodでは、結果を常に 0 以上にする考え方がよく使われます。
たとえば、数学的な意味で -1 mod 5 を考えると、結果を 4 と扱うことがあります。
しかし、C#で次のコードを書くと、結果は -1 になります。
C#Console.WriteLine(-1 % 5); // -1
この違いは重要です。
C#の % は「数学のmodそのもの」ではなく、「C#の仕様に従った余りを求める演算子」と考えるべきです。
特に、配列の添字を循環させる処理で、マイナス方向に移動する場合は注意が必要です。
4-4. 負の数で想定外の結果になりやすいケース
負の数の剰余でバグが起きやすい例として、配列のインデックス計算があります。
C#string[] items = { "A", "B", "C" };
int index = -1 % items.Length;
Console.WriteLine(index); // -1
items.Length は 3 なので、-1 % 3 を計算しています。
C#では結果が -1 になります。
この index を使って配列にアクセスすると、エラーになります。
C#Console.WriteLine(items[index]); // エラー
配列の添字に -1 は使えないため、IndexOutOfRangeException の原因になります。
「剰余を使っているから必ず 0 以上になる」と思い込むのは危険です。
4-5. 常に正の余りを得たい場合の書き方
負の数を扱う場合でも、常に 0 以上の余りを得たい場合は、次のように書くことがあります。
C#int mod = 5;
int value = -1;
int result = ((value % mod) + mod) % mod;
Console.WriteLine(result); // 4
この書き方では、まず value % mod を計算し、その結果に mod を足して、もう一度 % mod を行います。
計算の流れは次の通りです。
-1 % 5 = -1
-1 + 5 = 4
4 % 5 = 4
これにより、結果を 0 から mod - 1 の範囲に収めることができます。
メソッドにすると、次のように書けます。
C#static int PositiveMod(int value, int mod)
{
return ((value % mod) + mod) % mod;
}
Console.WriteLine(PositiveMod(-1, 5)); // 4
Console.WriteLine(PositiveMod(6, 5)); // 1
負の数を含む循環処理では、このような補正を入れると安全です。
4-6. 配列のインデックス計算で負の余りに注意する
配列の添字を循環させる処理で、前方向だけでなく後ろ方向にも移動する場合は、負の余りに注意しましょう。
たとえば、現在位置から1つ前に戻る処理を考えます。
C#string[] items = { "A", "B", "C" };
int currentIndex = 0;
int nextIndex = (currentIndex - 1) % items.Length;
Console.WriteLine(nextIndex); // -1
このままだと、nextIndex は -1 になってしまいます。
正しく循環させたい場合は、次のようにします。
C#string[] items = { "A", "B", "C" };
int currentIndex = 0;
int nextIndex = ((currentIndex - 1) % items.Length + items.Length) % items.Length;
Console.WriteLine(nextIndex); // 2
Console.WriteLine(items[nextIndex]); // C
0 のひとつ前を 2 として扱えるため、配列の末尾に戻る処理を安全に実装できます。
5. 小数・double・decimalで剰余演算子は使える?
5-1. C#では浮動小数点数にも%を使える
C#では、整数だけでなく、float、double、decimal のような小数にも % を使えます。C#リファレンスでも、float、double、decimal に対する剰余演算の動作が説明されています。
たとえば、次のようなコードが書けます。
C#Console.WriteLine(5.5 % 2.0);
実行結果は次のようになります。
1.5
5.5 を 2.0 で割ると、2.0 × 2 = 4.0 で、残りは 1.5 です。
ただし、小数の剰余は整数よりも注意が必要です。特に double や float は丸め誤差が発生することがあります。
5-2. double型での剰余計算例
double 型で剰余を求める例を見てみましょう。
C#double a = 5.9;
double b = 3.1;
double result = a % b;
Console.WriteLine(result);
実行すると、環境によって表示形式に差はありますが、2.8 に近い値が出力されます。
2.8
もうひとつ例を見てみます。
C#double price = 10.5;
double unit = 3.0;
double remainder = price % unit;
Console.WriteLine(remainder); // 1.5
小数でも % 自体は使えますが、double は2進数で小数を扱うため、期待した値とわずかに違う結果になることがあります。
5-3. decimal型での剰余計算例
decimal 型でも剰余演算子を使えます。
C#decimal a = 5.9m;
decimal b = 3.1m;
decimal result = a % b;
Console.WriteLine(result); // 2.8
decimal の数値リテラルには、末尾に m を付けます。
C#decimal price = 1000.75m;
decimal unit = 300.00m;
decimal remainder = price % unit;
Console.WriteLine(remainder); // 100.75
decimal は、金額のように10進数として扱いたい値に向いています。
5-4. 小数の剰余で丸め誤差に注意する
double や float を使う場合は、丸め誤差に注意が必要です。
C#リファレンスでも、浮動小数点数の表現や演算の制約により、計算結果が数学的に期待する値と異なる場合があると説明されています。たとえば、.41f % .2f の結果が 0.01 ちょうどではなく、近似値になる例が示されています。
次のようなコードを考えてみます。
C#double result = 0.3 % 0.1;
Console.WriteLine(result);
数学的には 0 になりそうですが、double の内部表現の都合で、非常に小さな誤差が出ることがあります。
そのため、小数の剰余結果を比較するときに、次のような書き方は注意が必要です。
C#if (result == 0.0)
{
Console.WriteLine("割り切れます");
}
double の計算結果を比較する場合は、許容誤差を使うことがあります。
C#double result = 0.3 % 0.1;
double epsilon = 0.0000001;
if (Math.Abs(result) < epsilon)
{
Console.WriteLine("ほぼ0です");
}
整数の剰余と同じ感覚で小数を扱うと、思わぬ判定ミスにつながることがあります。
5-5. 金額計算ではdecimalを使うべき理由
金額計算では、一般的に double よりも decimal を使うべきです。
double は科学計算や座標計算などには便利ですが、2進数で小数を近似するため、金額のように正確な10進数が重要な場面では誤差が問題になることがあります。
一方、decimal は10進数の計算に向いているため、金額、税率、通貨、請求金額などを扱う場合に適しています。
C#decimal total = 1000.00m;
decimal unit = 300.00m;
decimal remainder = total % unit;
Console.WriteLine(remainder); // 100.00
金額の余りを計算する場合は、decimal を使うと意図が伝わりやすく、誤差のリスクも抑えやすくなります。
6. C#の剰余演算子でよくあるエラーと原因
6-1. 0で割るとDivideByZeroExceptionが発生する
C#の整数型で % を使うとき、右側の値が 0 になると DivideByZeroException が発生します。C#リファレンスでも、整数の0除算は常に DivideByZeroException をスローすると説明されています。
C#int a = 10;
int b = 0;
int result = a % b; // DivideByZeroException
% は割り算に関係する演算子なので、割る数が 0 になると計算できません。
次のように、直接 0 を指定した場合も同じです。
C#Console.WriteLine(10 % 0); // エラー
初心者がよく遭遇するエラーなので、剰余演算子を使うときは右側の値に注意しましょう。
なお、double や float の演算では整数と異なる動作をする場合がありますが、初心者のうちはまず「整数の % では右側を 0 にしない」と覚えておくのが大切です。
6-2. 変数が0になる可能性がある場合の対策
実際のプログラムでは、右側の値が変数になることが多いです。
C#int total = 10;
int divisor = GetDivisor();
int result = total % divisor;
このとき、GetDivisor() が 0 を返す可能性があるなら危険です。
安全に書くには、剰余を計算する前に 0 でないことを確認します。
C#int total = 10;
int divisor = 0;
if (divisor != 0)
{
int result = total % divisor;
Console.WriteLine(result);
}
else
{
Console.WriteLine("0では割れません");
}
メソッド化するなら、次のように書けます。
C#static int? SafeRemainder(int a, int b)
{
if (b == 0)
{
return null;
}
return a % b;
}
使う側では、null かどうかを確認します。
C#int? result = SafeRemainder(10, 0);
if (result.HasValue)
{
Console.WriteLine(result.Value);
}
else
{
Console.WriteLine("計算できません");
}
入力値や外部データを使う場合は、右側の値が 0 にならないか必ず確認しましょう。
6-3. int同士の割り算で小数が消える問題
剰余演算子そのもののエラーではありませんが、/ と % を一緒に使うときに、int 同士の割り算で小数が消えることがあります。
C#int a = 10;
int b = 3;
Console.WriteLine(a / b); // 3
10 ÷ 3 は本来 3.333... ですが、int 同士の割り算では結果が整数になるため、表示されるのは 3 です。
小数の結果がほしい場合は、どちらかを double にします。
C#int a = 10;
int b = 3;
double result = (double)a / b;
Console.WriteLine(result); // 3.3333333333333335
商と余りを求める場合は、整数のままで問題ありません。
C#int quotient = a / b; // 3
int remainder = a % b; // 1
しかし、「割り算の結果」と「余り」を混同しないようにしましょう。
6-4. 負の数の結果を勘違いする問題
C#の % では、負の数の結果を勘違いしやすいです。
C#Console.WriteLine(-5 % 4); // -1
数学的なmodの感覚で 3 になると思っていると、バグの原因になります。
特に、次のような条件式では注意が必要です。
C#int value = -1;
if (value % 5 == 4)
{
Console.WriteLine("4です");
}
C#では -1 % 5 は -1 なので、この条件は false になります。
常に正の余りを期待する場合は、補正処理を入れましょう。
C#int value = -1;
int mod = 5;
int result = ((value % mod) + mod) % mod;
Console.WriteLine(result); // 4
負の数を扱う可能性があるコードでは、C#の剰余演算子の仕様を意識することが大切です。
6-5. 配列の範囲外アクセスにつながるケース
剰余演算子は配列の添字を循環させるのに便利ですが、負の値が入ると範囲外アクセスの原因になります。
C#string[] names = { "Alice", "Bob", "Charlie" };
int index = -1 % names.Length;
Console.WriteLine(names[index]); // エラー
index は -1 になるため、配列の添字として使えません。
安全に書くなら、次のようにします。
C#string[] names = { "Alice", "Bob", "Charlie" };
int value = -1;
int index = ((value % names.Length) + names.Length) % names.Length;
Console.WriteLine(names[index]); // Charlie
配列や List の添字に % を使う場合は、「結果が必ず 0 以上になるか」を確認しましょう。
6-6. 型の違いによるコンパイルエラー
C#では、型の組み合わせによってコンパイルエラーになる場合があります。
たとえば、decimal と double をそのまま混ぜることはできません。
C#decimal a = 10.5m;
double b = 3.0;
var result = a % b; // コンパイルエラー
decimal と double は暗黙的に変換されないため、型をそろえる必要があります。
decimal にそろえる場合は、次のようにします。
C#decimal a = 10.5m;
decimal b = 3.0m;
decimal result = a % b;
Console.WriteLine(result);
double にそろえる場合は、次のようにキャストします。
C#decimal a = 10.5m;
double b = 3.0;
double result = (double)a % b;
Console.WriteLine(result);
ただし、金額計算なら decimal にそろえる方が適しています。
7. Math.DivRemを使って商と余りを同時に求める方法
7-1. Math.DivRemとは
Math.DivRem は、割り算の商と余りを同時に求めるためのメソッドです。
C#では、/ で商、% で余りを別々に求められます。
C#int quotient = 10 / 3;
int remainder = 10 % 3;
一方、Math.DivRem を使うと、商と余りをひとつの処理で取得できます。Microsoftのリファレンスでも、Math.DivRem は2つの数値の商を計算し、余りを出力パラメーターで返すメソッドとして説明されています。
7-2. Math.DivRemの基本構文
従来からよく使われる Math.DivRem の基本構文は次の通りです。
C#int remainder;
int quotient = Math.DivRem(a, b, out remainder);
quotient に商が入り、remainder に余りが入ります。
具体例を見てみましょう。
C#int a = 10;
int b = 3;
int remainder;
int quotient = Math.DivRem(a, b, out remainder);
Console.WriteLine($"商: {quotient}");
Console.WriteLine($"余り: {remainder}");
実行結果は次のようになります。
商: 3
余り: 1
新しい.NETの環境では、タプル形式で商と余りを受け取れるオーバーロードもあります。
C#var result = Math.DivRem(10, 3);
Console.WriteLine(result.Quotient); // 3
Console.WriteLine(result.Remainder); // 1
ただし、対象の.NETバージョンによって使える形式が異なる場合があるため、初心者はまず out を使う書き方を覚えておくとよいでしょう。
7-3. / と % を別々に使う場合との違い
/ と % を別々に使う場合、コードは次のようになります。
C#int a = 10;
int b = 3;
int quotient = a / b;
int remainder = a % b;
Math.DivRem を使う場合は、次のようになります。
C#int a = 10;
int b = 3;
int remainder;
int quotient = Math.DivRem(a, b, out remainder);
どちらも、商と余りを取得するという点では同じです。
初心者にとっては、/ と % を別々に使う方が直感的かもしれません。
C#int quotient = a / b;
int remainder = a % b;
一方で、「商と余りをセットで求めている」という意図を明確にしたい場合は、Math.DivRem が便利です。
7-4. Math.DivRemを使ったサンプルコード
実際に、秒数を分と秒に変換する処理で Math.DivRem を使ってみましょう。
C#int totalSeconds = 125;
int seconds;
int minutes = Math.DivRem(totalSeconds, 60, out seconds);
Console.WriteLine($"{minutes}分{seconds}秒");
実行結果は次の通りです。
2分5秒
Math.DivRem(totalSeconds, 60, out seconds) によって、商である 2 が minutes に入り、余りである 5 が seconds に入ります。
もうひとつ、ページ数を求める例です。
C#int totalItems = 23;
int itemsPerPage = 5;
int remainingItems;
int fullPages = Math.DivRem(totalItems, itemsPerPage, out remainingItems);
Console.WriteLine($"満杯のページ数: {fullPages}");
Console.WriteLine($"余りのアイテム数: {remainingItems}");
実行結果は次のようになります。
満杯のページ数: 4
余りのアイテム数: 3
7-5. Math.DivRemを使うと便利な場面
Math.DivRem は、商と余りを同時に使う場面で便利です。
たとえば、秒数を分と秒に分ける処理、アイテム数をページ数と余りに分ける処理、お金を単位ごとに分解する処理、ゲーム内のスコアやレベル計算などで使えます。
C#int coins = 137;
int remainder;
int hundreds = Math.DivRem(coins, 100, out remainder);
Console.WriteLine($"100単位: {hundreds}");
Console.WriteLine($"残り: {remainder}");
実行結果は次の通りです。
100単位: 1
残り: 37
/ と % を使っても書けますが、商と余りのセットであることを明確にしたい場合は Math.DivRem を検討するとよいでしょう。
8. C#の剰余演算子を使うときの注意点
8-1. 右側の値が0でないことを確認する
剰余演算子を使うときに最も重要なのは、右側の値が 0 でないことです。
C#int result = a % b;
この場合、b が 0 になると問題が発生します。
安全に書くなら、次のようにチェックします。
C#if (b != 0)
{
int result = a % b;
Console.WriteLine(result);
}
else
{
Console.WriteLine("割る数が0です");
}
ユーザー入力や外部ファイル、APIから取得した値を使う場合は、特に注意が必要です。
C#Console.Write("割る数を入力してください: ");
int divisor = int.Parse(Console.ReadLine());
if (divisor == 0)
{
Console.WriteLine("0では割れません");
}
else
{
Console.WriteLine(10 % divisor);
}
% の右側に来る値は、必ず事前に確認する習慣をつけましょう。
8-2. 負の数を扱う場合は仕様を確認する
C#の剰余演算子では、負の数の結果が数学的なmodと異なる場合があります。
C#Console.WriteLine(-1 % 5); // -1
常に正の余りを期待している場合、この結果は想定外かもしれません。
負の数を扱う処理では、次のように補正します。
C#int value = -1;
int mod = 5;
int result = ((value % mod) + mod) % mod;
Console.WriteLine(result); // 4
特に、配列の添字、カレンダー計算、曜日計算、循環バッファ、ゲームの座標計算などでは、負の値が混ざる可能性があります。
C#の % は「常に正のmodを返す演算子」ではないことを覚えておきましょう。
8-3. 読みやすい条件式にする
剰余演算子を使った条件式は便利ですが、複雑に書きすぎると読みにくくなります。
たとえば、次のコードは少し読みづらいです。
C#if (count % 3 == 0 && count % 5 == 0 && count % 2 != 0)
{
Console.WriteLine("条件に一致しました");
}
処理の意味が重要な場合は、変数に分けると読みやすくなります。
C#bool isMultipleOf3 = count % 3 == 0;
bool isMultipleOf5 = count % 5 == 0;
bool isOdd = count % 2 != 0;
if (isMultipleOf3 && isMultipleOf5 && isOdd)
{
Console.WriteLine("条件に一致しました");
}
変数名を見るだけで、何を判定しているのかがわかります。
C#のコードは、動くだけでなく、あとから読んだ人が理解しやすいことも大切です。
8-4. 「%」を多用しすぎず意図が伝わる変数名を使う
剰余演算子は便利ですが、1行に何度も使うと意図がわかりにくくなります。
C#int index = ((current - offset) % length + length) % length;
このコード自体はよくある書き方ですが、初心者や他の開発者には少し読みにくいかもしれません。
意味のあるメソッドに分けると、意図が伝わりやすくなります。
C#static int PositiveMod(int value, int mod)
{
return ((value % mod) + mod) % mod;
}
int index = PositiveMod(current - offset, length);
このようにすると、「正の余りを求めている」という意図が明確になります。
また、変数名も大切です。
C#int remainder = total % pageSize;
より具体的にするなら、次のように書けます。
C#int remainingItems = totalItems % itemsPerPage;
何の余りなのかが伝わる名前にすると、コードの可読性が上がります。
8-5. 他の言語のmod演算と結果が違う場合がある
プログラミング言語によって、剰余やmodの扱いは異なる場合があります。
特に負の数を扱うとき、C#、Python、JavaScript、数学的なmodで結果が異なることがあります。
C#では次の結果になります。
C#Console.WriteLine(-1 % 5); // -1
一方で、言語やライブラリによっては、同じような計算で 4 を返すものもあります。
他の言語からC#に移ってきた人は、「% の記号が同じだから動作も同じ」と思い込まないようにしましょう。
負の数を含む剰余計算では、その言語の仕様を確認することが重要です。
9. 初心者向け練習問題で理解を深める
9-1. 余りを求める基本問題
まずは、基本的な余りを求める問題です。
次の計算結果を予想してから、C#で実行してみましょう。
C#Console.WriteLine(10 % 3);
Console.WriteLine(14 % 5);
Console.WriteLine(20 % 4);
Console.WriteLine(7 % 2);
答えは次の通りです。
1
4
0
1
解説します。
10 ÷ 3 = 3 余り 1
14 ÷ 5 = 2 余り 4
20 ÷ 4 = 5 余り 0
7 ÷ 2 = 3 余り 1
余りが 0 の場合は、割り切れるという意味です。
9-2. 偶数・奇数を判定する問題
次の整数が偶数か奇数かを判定するコードを書いてみましょう。
C#int num = 13;
解答例です。
C#int num = 13;
if (num % 2 == 0)
{
Console.WriteLine("偶数です");
}
else
{
Console.WriteLine("奇数です");
}
実行結果は次の通りです。
奇数です
13 % 2 は 1 なので、13 は奇数です。
別の値でも試してみましょう。
C#int num = 24;
if (num % 2 == 0)
{
Console.WriteLine("偶数です");
}
else
{
Console.WriteLine("奇数です");
}
24 % 2 は 0 なので、偶数です。
9-3. 倍数を判定する問題
次の整数が 3 の倍数かどうかを判定してみましょう。
C#int num = 21;
解答例です。
C#int num = 21;
if (num % 3 == 0)
{
Console.WriteLine("3の倍数です");
}
else
{
Console.WriteLine("3の倍数ではありません");
}
実行結果は次の通りです。
3の倍数です
21 % 3 は 0 なので、21 は 3 の倍数です。
次は、5 の倍数を判定してみます。
C#int num = 42;
if (num % 5 == 0)
{
Console.WriteLine("5の倍数です");
}
else
{
Console.WriteLine("5の倍数ではありません");
}
実行結果は次のようになります。
5の倍数ではありません
42 % 5 は 2 なので、5 では割り切れません。
9-4. 秒数を分と秒に変換する問題
次の秒数を「分」と「秒」に変換してみましょう。
C#int totalSeconds = 185;
解答例です。
C#int totalSeconds = 185;
int minutes = totalSeconds / 60;
int seconds = totalSeconds % 60;
Console.WriteLine($"{minutes}分{seconds}秒");
実行結果は次の通りです。
3分5秒
185 ÷ 60 は、商が 3、余りが 5 です。
185秒 = 3分5秒
/ で分を求め、% で残りの秒を求めるのがポイントです。
9-5. 配列の要素を順番に循環表示する問題
次の配列を使って、要素を10回表示してみましょう。
C#string[] fruits = { "りんご", "バナナ", "みかん" };
期待する表示は、次のように繰り返される形です。
りんご
バナナ
みかん
りんご
バナナ
みかん
...
解答例です。
C#string[] fruits = { "りんご", "バナナ", "みかん" };
for (int i = 0; i < 10; i++)
{
int index = i % fruits.Length;
Console.WriteLine(fruits[index]);
}
fruits.Length は 3 です。
i % 3 の結果は、0、1、2 を繰り返します。
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
このように、剰余演算子を使うと配列の添字を循環させられます。
9-6. 負の数の剰余を確認する問題
最後に、負の数の剰余を確認してみましょう。
次のコードの結果を予想してください。
C#Console.WriteLine(5 % 4);
Console.WriteLine(5 % -4);
Console.WriteLine(-5 % 4);
Console.WriteLine(-5 % -4);
実行結果は次の通りです。
1
1
-1
-1
C#では、余りの符号は左側の値に合わせられます。
左側が 5 の場合、結果は正の 1 です。
C#Console.WriteLine(5 % 4); // 1
Console.WriteLine(5 % -4); // 1
左側が -5 の場合、結果は負の -1 です。
C#Console.WriteLine(-5 % 4); // -1
Console.WriteLine(-5 % -4); // -1
負の数を使う場合は、実際にコードを実行して動作を確認しておくと安心です。
10. C#の剰余演算子に関するよくある質問
10-1. C#の%は「割り算の余り」という意味ですか?
はい。C#の % は、割り算をしたときの余りを求める演算子です。
C#Console.WriteLine(10 % 3); // 1
10 ÷ 3 は、商が 3、余りが 1 なので、10 % 3 の結果は 1 です。
C#では、この % を剰余演算子、または余りを求める演算子と呼びます。
10-2. C#で商と余りを同時に求めるには?
/ と % を使って、商と余りをそれぞれ求められます。
C#int a = 10;
int b = 3;
int quotient = a / b;
int remainder = a % b;
Console.WriteLine($"商: {quotient}");
Console.WriteLine($"余り: {remainder}");
実行結果は次の通りです。
商: 3
余り: 1
また、Math.DivRem を使う方法もあります。
C#int remainder;
int quotient = Math.DivRem(10, 3, out remainder);
Console.WriteLine($"商: {quotient}");
Console.WriteLine($"余り: {remainder}");
商と余りをセットで扱いたい場合は、Math.DivRem も便利です。
10-3. C#で負の数の余りがマイナスになるのはなぜ?
C#では、余りの符号が左側の値に合わせられるためです。
C#Console.WriteLine(-5 % 4); // -1
左側の値が -5 なので、結果もマイナスになります。
数学的なmodでは正の値を期待する場合がありますが、C#の % は必ずしも数学のmodと同じではありません。
負の数を扱うときは、C#の仕様を意識してコードを書く必要があります。
10-4. C#で常に正の余りを取得するには?
常に正の余りを取得したい場合は、次のように補正します。
C#int value = -1;
int mod = 5;
int result = ((value % mod) + mod) % mod;
Console.WriteLine(result); // 4
メソッドにすると使いやすくなります。
C#static int PositiveMod(int value, int mod)
{
return ((value % mod) + mod) % mod;
}
使用例です。
C#Console.WriteLine(PositiveMod(-1, 5)); // 4
Console.WriteLine(PositiveMod(6, 5)); // 1
配列の循環インデックスや曜日計算などでは、このような正の剰余が必要になることがあります。
10-5. C#で小数に%を使ってもよいですか?
はい。C#では、double や decimal などの小数にも % を使えます。
C#double a = 5.5;
double b = 2.0;
Console.WriteLine(a % b); // 1.5
decimal でも使えます。
C#decimal a = 5.9m;
decimal b = 3.1m;
Console.WriteLine(a % b); // 2.8
ただし、double や float では丸め誤差が発生することがあります。
金額計算のように10進数としての正確さが重要な場合は、decimal を使うのが一般的です。
10-6. 0で割ったときのエラーを防ぐには?
剰余演算子を使う前に、右側の値が 0 でないことを確認します。
C#int a = 10;
int b = 0;
if (b != 0)
{
int result = a % b;
Console.WriteLine(result);
}
else
{
Console.WriteLine("0では割れません");
}
メソッドにする場合は、例外を避けるために 0 チェックを入れます。
C#static bool TryRemainder(int a, int b, out int result)
{
if (b == 0)
{
result = 0;
return false;
}
result = a % b;
return true;
}
使用例です。
C#if (TryRemainder(10, 3, out int result))
{
Console.WriteLine(result);
}
else
{
Console.WriteLine("計算できません");
}
ユーザー入力を使う場合や、変数の値が変化する場合は、必ず 0 の可能性を考慮しましょう。
まとめ
C#の剰余演算子 % は、割り算をしたときの余りを求める演算子です。
C#Console.WriteLine(10 % 3); // 1
10 ÷ 3 は、商が 3、余りが 1 なので、10 % 3 は 1 になります。
剰余演算子は、偶数・奇数の判定、倍数チェック、配列や List の添字の循環、時間変換、一定回数ごとの処理、ゲームやUIの周期処理など、多くの場面で使われます。
C#if (num % 2 == 0)
{
Console.WriteLine("偶数です");
}
また、/ と % を組み合わせると、商と余りをセットで扱えます。
C#int quotient = 10 / 3; // 3
int remainder = 10 % 3; // 1
商と余りを同時に求めたい場合は、Math.DivRem も使えます。
C#int remainder;
int quotient = Math.DivRem(10, 3, out remainder);
一方で、C#の剰余演算子には注意点もあります。
右側の値が 0 になると、整数では DivideByZeroException が発生します。
C#int result = 10 % 0; // エラー
負の数を扱う場合、C#では余りの符号が左側の値に合わせられます。
C#Console.WriteLine(-5 % 4); // -1
常に正の余りがほしい場合は、次のように補正します。
C#int result = ((value % mod) + mod) % mod;
小数にも % は使えますが、double や float では丸め誤差に注意が必要です。金額計算では decimal を使うとよいでしょう。
C#の剰余演算子は、基本を理解すれば非常に便利な演算子です。まずは 10 % 3 が 1 になる理由を理解し、偶数判定や倍数判定などの簡単な例から使い慣れていきましょう。

