C#の切り捨て方法を完全解説|Math.Truncate・Math.Floorの違いと桁数指定のサンプルコード
はじめに
C#で数値を「切り捨て」したい場面は、金額計算、割合計算、税計算、表示用の数値調整、集計処理などでよくあります。
ただし、C#の切り捨てにはいくつかの方法があり、特に混同しやすいのが Math.Truncate と Math.Floor の違いです。
どちらも小数部分を取り除くように見えますが、負の数を扱うと結果が変わります。
C#Console.WriteLine(Math.Truncate(12.9)); // 12
Console.WriteLine(Math.Floor(12.9)); // 12
Console.WriteLine(Math.Truncate(-12.9)); // -12
Console.WriteLine(Math.Floor(-12.9)); // -13
正の数だけを扱う場合は同じ結果になることが多いですが、負の数を扱う可能性がある場合は、どちらを使うかを明確に選ぶ必要があります。
この記事では、C#で切り捨てを行う基本的な方法から、Math.Truncate と Math.Floor の違い、小数第2位まで残すような桁数指定、金額計算での注意点まで、サンプルコード付きで解説します。
1. C#で「切り捨て」を行う方法の全体像
1-1. C#における切り捨てとは
C#における切り捨てとは、数値の小数部分や指定した桁より下の値を取り除く処理のことです。
たとえば、次のような処理が切り捨てに該当します。
C#12.987m → 12m
12.987m → 12.98m
12345m → 12300m
C#でよく使われる切り捨て方法は、主に次のとおりです。
| 方法 | 主な用途 |
|---|---|
Math.Truncate | 小数点以下を0に近い方向へ切り捨てる |
Math.Floor | 小数点以下を負の無限大方向へ切り捨てる |
int など整数型へのキャスト | 小数部分を削除して整数にする |
| 10の累乗を使った計算 | 小数第2位まで残すなど、桁数を指定する |
decimal 型での計算 | 金額や税額など、誤差を避けたい計算に使う |
Math.Truncate は「0に近い方向」へ丸めるメソッドで、Math.Floor は「指定した数以下の最大の整数」を返すメソッドです。Microsoft公式ドキュメントでも、Math.Truncate は0方向への丸め、Math.Floor は負の無限大方向への丸めとして説明されています。
1-2. 小数点以下を切り捨てたいケース
もっとも基本的な切り捨ては、小数点以下をすべて削除する処理です。
C#decimal value = 123.456m;
decimal result = Math.Truncate(value);
Console.WriteLine(result); // 123
小数点以下を単純に取り除きたい場合は、基本的に Math.Truncate を使うと意図が伝わりやすくなります。
C#double value = 98.76;
double result = Math.Truncate(value);
Console.WriteLine(result); // 98
「小数部分を消す」という目的が明確な場合、Math.Truncate は読みやすく、安全に意図を表現できます。
1-3. 指定した桁数で切り捨てたいケース
実務では、小数点以下をすべて削除するだけでなく、「小数第2位まで残して切り捨てたい」というケースも多くあります。
たとえば、次のような処理です。
C#12.3456m → 12.34m
98.7654m → 98.76m
C#には「指定した小数桁で切り捨てる専用メソッド」はありません。
そのため、次のように10の累乗を掛けてから切り捨て、最後に同じ数で割る方法を使います。
C#decimal value = 12.3456m;
decimal result = Math.Truncate(value * 100m) / 100m;
Console.WriteLine(result); // 12.34
小数第2位まで残したい場合は 100、小数第3位まで残したい場合は 1000 を使います。
1-4. 負の数を扱うときに注意すべきケース
C#の切り捨てで特に注意が必要なのは、負の数を扱う場合です。
Math.Truncate と Math.Floor は、正の数では同じ結果になることが多いですが、負の数では結果が変わります。
C#Console.WriteLine(Math.Truncate(-1.9)); // -1
Console.WriteLine(Math.Floor(-1.9)); // -2
Math.Truncate(-1.9) は0に近い方向へ進むため -1 になります。
一方、Math.Floor(-1.9) は負の無限大方向へ進むため -2 になります。
「小数部分を単純に削除したい」のか、「必ず元の値以下の整数にしたい」のかによって、使うメソッドを選びましょう。
2. C#で小数点以下を切り捨てる基本的な方法
2-1. Math.Truncateを使う方法
Math.Truncate は、C#で小数点以下を切り捨てる代表的なメソッドです。
C#decimal value = 123.987m;
decimal result = Math.Truncate(value);
Console.WriteLine(result); // 123
double 型にも使えます。
C#double value = 123.987;
double result = Math.Truncate(value);
Console.WriteLine(result); // 123
Math.Truncate の特徴は、戻り値が整数型ではなく、引数に応じて decimal または double になることです。
C#decimal decimalValue = 123.987m;
decimal decimalResult = Math.Truncate(decimalValue);
double doubleValue = 123.987;
double doubleResult = Math.Truncate(doubleValue);
つまり、Math.Truncate を使っただけでは int 型にはなりません。
整数型として扱いたい場合は、必要に応じてキャストや変換を行います。
C#decimal value = 123.987m;
int result = (int)Math.Truncate(value);
Console.WriteLine(result); // 123
2-2. Math.Floorを使う方法
Math.Floor も小数点以下を切り捨てるように見えるメソッドです。
C#decimal value = 123.987m;
decimal result = Math.Floor(value);
Console.WriteLine(result); // 123
正の数だけを扱う場合、Math.Truncate と同じ結果になることが多いです。
C#Console.WriteLine(Math.Truncate(123.987)); // 123
Console.WriteLine(Math.Floor(123.987)); // 123
ただし、Math.Floor は「指定した数以下の最大の整数」を返します。これは負の数で大きな違いになります。
C#Console.WriteLine(Math.Floor(-123.987)); // -124
「常に元の値以下にしたい」「数学的な床関数として扱いたい」場合は Math.Floor を使います。
2-3. int型へキャストして切り捨てる方法
小数を int 型へキャストすると、小数部分は削除されます。
C#double value = 123.987;
int result = (int)value;
Console.WriteLine(result); // 123
decimal 型でも同様です。
C#decimal value = 123.987m;
int result = (int)value;
Console.WriteLine(result); // 123
負の数の場合は、0に近い方向へ小数部分が削除されます。
C#double value = -123.987;
int result = (int)value;
Console.WriteLine(result); // -123
この挙動は Math.Truncate に近いです。
ただし、キャストは「型変換」が主目的なので、コードを読んだ人に「切り捨てを意図している」と伝わりにくい場合があります。
C#int result = (int)value;
より意図を明確にするなら、次のように書くほうが読みやすくなります。
C#int result = (int)Math.Truncate(value);
2-4. decimal型で切り捨てる方法
金額計算や税額計算では、decimal 型を使うのが基本です。
C#decimal price = 1980m;
decimal taxRate = 0.1m;
decimal tax = Math.Truncate(price * taxRate);
Console.WriteLine(tax); // 198
decimal 型のリテラルには末尾に m を付けます。
C#decimal value = 123.456m;
m を付けないと double として扱われるため、decimal 型に代入するとコンパイルエラーになります。
C#// コンパイルエラー
// decimal value = 123.456;
正しくは次のように書きます。
C#decimal value = 123.456m;
decimal は、金額計算のように有効桁数が必要で丸め誤差を抑えたい場面に適した型として説明されています。
2-5. double型・float型で切り捨てる方法
double 型や float 型でも、Math.Truncate や Math.Floor は使えます。
C#double value = 123.456;
double result = Math.Truncate(value);
Console.WriteLine(result); // 123
float 型の場合、Math.Truncate に渡すと double として処理されます。
C#float value = 123.456f;
double result = Math.Truncate(value);
Console.WriteLine(result); // 123
float の結果を float に戻したい場合はキャストします。
C#float value = 123.456f;
float result = (float)Math.Truncate(value);
Console.WriteLine(result); // 123
ただし、double や float は2進浮動小数点数のため、10進数を完全に表せないことがあります。
金額計算では double や float ではなく、decimal を使うほうが安全です。
3. Math.TruncateとMath.Floorの違い
3-1. Math.Truncateは0に近い方向へ切り捨てる
Math.Truncate は、小数部分を削除して0に近い方向へ丸めます。
C#Console.WriteLine(Math.Truncate(3.9)); // 3
Console.WriteLine(Math.Truncate(3.1)); // 3
Console.WriteLine(Math.Truncate(-3.1)); // -3
Console.WriteLine(Math.Truncate(-3.9)); // -3
正の数では小さくなる方向に進みます。
C#3.9 → 3
負の数では大きくなる方向、つまり0に近づく方向に進みます。
C#-3.9 → -3
そのため、Math.Truncate は「小数部分を単純に取り除きたい」ときに向いています。
3-2. Math.Floorは負の無限大方向へ切り捨てる
Math.Floor は、指定した数以下の最大の整数を返します。
C#Console.WriteLine(Math.Floor(3.9)); // 3
Console.WriteLine(Math.Floor(3.1)); // 3
Console.WriteLine(Math.Floor(-3.1)); // -4
Console.WriteLine(Math.Floor(-3.9)); // -4
正の数では Math.Truncate と同じ結果になります。
C#3.9 → 3
しかし、負の数ではより小さい整数になります。
C#-3.1 → -4
これは、Math.Floor が負の無限大方向へ丸めるためです。Microsoft公式ドキュメントでも、Math.Floor はIEEE 754に従う負の無限大方向への丸めとして説明されています。
3-3. 正の数での挙動の違い
正の数だけを見ると、Math.Truncate と Math.Floor は同じように見えます。
C#double[] values = { 1.1, 1.5, 1.9, 10.01, 10.99 };
foreach (double value in values)
{
Console.WriteLine($"{value} : Truncate={Math.Truncate(value)}, Floor={Math.Floor(value)}");
}
出力例は次のとおりです。
1.1 : Truncate=1, Floor=1
1.5 : Truncate=1, Floor=1
1.9 : Truncate=1, Floor=1
10.01 : Truncate=10, Floor=10
10.99 : Truncate=10, Floor=10
正の数だけを扱う処理では、どちらを使っても結果が同じになることが多いです。
ただし、意味は異なります。
Math.Truncate は「小数部分を取り除く」、Math.Floor は「元の値以下の最大の整数を返す」です。
3-4. 負の数での挙動の違い
負の数では、Math.Truncate と Math.Floor の違いがはっきり出ます。
C#double[] values = { -1.1, -1.5, -1.9, -10.01, -10.99 };
foreach (double value in values)
{
Console.WriteLine($"{value} : Truncate={Math.Truncate(value)}, Floor={Math.Floor(value)}");
}
出力例は次のとおりです。
-1.1 : Truncate=-1, Floor=-2
-1.5 : Truncate=-1, Floor=-2
-1.9 : Truncate=-1, Floor=-2
-10.01 : Truncate=-10, Floor=-11
-10.99 : Truncate=-10, Floor=-11
たとえば、-1.9 の小数部分を取り除くなら -1 です。
しかし、-1.9 以下の最大の整数は -2 です。
この違いを理解せずに使うと、返金額、差額、マイナス補正、赤字金額などの計算でバグにつながる可能性があります。
3-5. TruncateとFloorの使い分け早見表
| 目的 | 使うメソッド | 例 |
|---|---|---|
| 小数部分を単純に削除したい | Math.Truncate | 12.9 → 12, -12.9 → -12 |
| 0に近い方向へ丸めたい | Math.Truncate | -1.8 → -1 |
| 必ず元の値以下にしたい | Math.Floor | 12.9 → 12, -12.9 → -13 |
| 数学的な床関数として扱いたい | Math.Floor | Floor(-1.2) → -2 |
| 正の数の金額を円未満切り捨てしたい | Math.Truncate または Math.Floor | 198.9 → 198 |
| 負の数もあり得る金額を処理したい | 要件に応じて選択 | 返金や差額では特に注意 |
実務では、単に「切り捨て」と書かれていても、0方向なのか、負の無限大方向なのかを確認することが重要です。
4. 桁数を指定して切り捨てる方法
4-1. 小数第1位で切り捨てるサンプルコード
小数第1位まで残して切り捨てたい場合は、10を掛けてから Math.Truncate し、最後に10で割ります。
C#decimal value = 12.345m;
decimal result = Math.Truncate(value * 10m) / 10m;
Console.WriteLine(result); // 12.3
考え方は次のとおりです。
12.345 × 10 = 123.45
123.45 を切り捨て = 123
123 ÷ 10 = 12.3
「小数第1位を切り捨てて整数にする」という意味で使う場合は、単純に Math.Truncate を使います。
C#decimal value = 12.345m;
decimal result = Math.Truncate(value);
Console.WriteLine(result); // 12
日本語の「小数第1位で切り捨て」は文脈によって意味が変わることがあります。
「小数第1位まで残す」のか、「小数第1位から下を捨てる」のかを明確にしましょう。
4-2. 小数第2位で切り捨てるサンプルコード
小数第2位まで残して切り捨てる場合は、100を使います。
C#decimal value = 12.3456m;
decimal result = Math.Truncate(value * 100m) / 100m;
Console.WriteLine(result); // 12.34
小数第2位まで残すとは、次のような処理です。
12.3456 → 12.34
98.7654 → 98.76
1.9999 → 1.99
四捨五入ではないため、次のように 12.349 も 12.34 になります。
C#decimal value = 12.349m;
decimal result = Math.Truncate(value * 100m) / 100m;
Console.WriteLine(result); // 12.34
4-3. 小数第3位以降で切り捨てるサンプルコード
小数第3位まで残して切り捨てる場合は、1000を使います。
C#decimal value = 12.34567m;
decimal result = Math.Truncate(value * 1000m) / 1000m;
Console.WriteLine(result); // 12.345
小数第4位まで残すなら10000です。
C#decimal value = 12.345678m;
decimal result = Math.Truncate(value * 10000m) / 10000m;
Console.WriteLine(result); // 12.3456
指定する小数桁数と掛ける値の関係は次のとおりです。
| 残したい桁数 | 掛ける値 |
|---|---|
| 小数第1位まで | 10 |
| 小数第2位まで | 100 |
| 小数第3位まで | 1000 |
| 小数第4位まで | 10000 |
4-4. 整数の10の位・100の位で切り捨てる方法
整数部分の桁を指定して切り捨てる場合は、先に割ってから切り捨て、最後に掛け直します。
10の位で切り捨てる、つまり1の位を捨てる場合は次のようにします。
C#decimal value = 12345m;
decimal result = Math.Truncate(value / 10m) * 10m;
Console.WriteLine(result); // 12340
100の位で切り捨てる、つまり10の位以下を捨てる場合は次のようにします。
C#decimal value = 12345m;
decimal result = Math.Truncate(value / 100m) * 100m;
Console.WriteLine(result); // 12300
1000の位で切り捨てる場合は、1000で割ってから切り捨てます。
C#decimal value = 12345m;
decimal result = Math.Truncate(value / 1000m) * 1000m;
Console.WriteLine(result); // 12000
負の数で「常に元の値以下」にしたい場合は、Math.Truncate ではなく Math.Floor を使います。
C#decimal value = -12345m;
decimal truncateResult = Math.Truncate(value / 100m) * 100m;
decimal floorResult = Math.Floor(value / 100m) * 100m;
Console.WriteLine(truncateResult); // -12300
Console.WriteLine(floorResult); // -12400
4-5. 桁数指定をメソッド化して再利用する方法
桁数指定の切り捨ては、毎回書くとミスが起きやすいため、メソッド化しておくと便利です。
C#static decimal TruncateDecimal(decimal value, int decimalPlaces)
{
decimal factor = 1m;
for (int i = 0; i < decimalPlaces; i++)
{
factor *= 10m;
}
return Math.Truncate(value * factor) / factor;
}
使い方は次のとおりです。
C#decimal value = 12.34567m;
Console.WriteLine(TruncateDecimal(value, 0)); // 12
Console.WriteLine(TruncateDecimal(value, 1)); // 12.3
Console.WriteLine(TruncateDecimal(value, 2)); // 12.34
Console.WriteLine(TruncateDecimal(value, 3)); // 12.345
負の小数桁数を受け取らないようにするなら、チェックを追加します。
C#static decimal TruncateDecimal(decimal value, int decimalPlaces)
{
if (decimalPlaces < 0)
{
throw new ArgumentOutOfRangeException(nameof(decimalPlaces), "小数桁数は0以上を指定してください。");
}
decimal factor = 1m;
for (int i = 0; i < decimalPlaces; i++)
{
factor *= 10m;
}
return Math.Truncate(value * factor) / factor;
}
decimal 型には Math.Pow の decimal 版がないため、金額計算では上記のように decimal のまま10を掛けていく方法が安全です。
5. C#の切り捨てサンプルコード集
5-1. Math.Truncateを使った基本コード
C#using System;
class Program
{
static void Main()
{
decimal value1 = 123.456m;
decimal value2 = -123.456m;
Console.WriteLine(Math.Truncate(value1)); // 123
Console.WriteLine(Math.Truncate(value2)); // -123
}
}
Math.Truncate は、正の数でも負の数でも0に近い方向へ丸めます。
小数点以下を単純に取り除きたい場合に使いやすいメソッドです。
5-2. Math.Floorを使った基本コード
C#using System;
class Program
{
static void Main()
{
decimal value1 = 123.456m;
decimal value2 = -123.456m;
Console.WriteLine(Math.Floor(value1)); // 123
Console.WriteLine(Math.Floor(value2)); // -124
}
}
Math.Floor は、元の値以下の最大の整数を返します。
負の数では Math.Truncate と結果が異なる点に注意してください。
5-3. キャストで小数点以下を切り捨てるコード
C#using System;
class Program
{
static void Main()
{
double value = 123.456;
int result = (int)value;
Console.WriteLine(result); // 123
}
}
負の数でも0方向に小数部分が削除されます。
C#double value = -123.456;
int result = (int)value;
Console.WriteLine(result); // -123
キャストは短く書けますが、値が int の範囲を超える場合は問題になります。
また、コードの意図が「切り捨て」なのか「型変換」なのか分かりにくくなる場合があります。
5-4. 任意の小数桁で切り捨てるコード
C#using System;
class Program
{
static void Main()
{
decimal value = 123.456789m;
Console.WriteLine(TruncateDecimal(value, 1)); // 123.4
Console.WriteLine(TruncateDecimal(value, 2)); // 123.45
Console.WriteLine(TruncateDecimal(value, 3)); // 123.456
}
static decimal TruncateDecimal(decimal value, int decimalPlaces)
{
if (decimalPlaces < 0)
{
throw new ArgumentOutOfRangeException(nameof(decimalPlaces));
}
decimal factor = 1m;
for (int i = 0; i < decimalPlaces; i++)
{
factor *= 10m;
}
return Math.Truncate(value * factor) / factor;
}
}
このメソッドを用意しておけば、小数第1位、小数第2位、小数第3位などを簡単に指定できます。
5-5. 金額計算で切り捨てるコード
金額計算では、decimal 型を使いましょう。
C#using System;
class Program
{
static void Main()
{
decimal price = 1980m;
decimal taxRate = 0.10m;
decimal tax = Math.Truncate(price * taxRate);
Console.WriteLine(tax); // 198
}
}
消費税などで「1円未満切り捨て」を行う場合は、次のように書けます。
C#decimal price = 999m;
decimal taxRate = 0.10m;
decimal tax = Math.Truncate(price * taxRate);
Console.WriteLine(tax); // 99
税込金額を求める場合は次のとおりです。
C#decimal price = 999m;
decimal taxRate = 0.10m;
decimal tax = Math.Truncate(price * taxRate);
decimal total = price + tax;
Console.WriteLine(total); // 1098
小数第2位まで残す金額計算をしたい場合は、桁数指定のメソッドを使います。
C#decimal amount = 1234.5678m;
decimal result = TruncateDecimal(amount, 2);
Console.WriteLine(result); // 1234.56
5-6. パーセント計算で切り捨てるコード
割合やパーセントを計算するときも、表示前に切り捨てたいことがあります。
C#using System;
class Program
{
static void Main()
{
decimal completed = 37m;
decimal total = 123m;
decimal rate = completed / total * 100m;
decimal result = Math.Truncate(rate * 10m) / 10m;
Console.WriteLine(result); // 30.0
}
}
小数第2位まで残す場合は、100を使います。
C#decimal completed = 37m;
decimal total = 123m;
decimal rate = completed / total * 100m;
decimal result = Math.Truncate(rate * 100m) / 100m;
Console.WriteLine(result); // 30.08
メソッド化しておくと、より読みやすくなります。
C#decimal rate = completed / total * 100m;
decimal result = TruncateDecimal(rate, 2);
Console.WriteLine(result); // 30.08
6. 四捨五入・切り上げとの違い
6-1. 切り捨て・四捨五入・切り上げの違い
切り捨て、四捨五入、切り上げは似ていますが、結果は異なります。
| 処理 | 内容 | 例 |
|---|---|---|
| 切り捨て | 指定桁より下を捨てる | 12.9 → 12 |
| 四捨五入 | 指定桁を基準に近い値へ丸める | 12.5 → 13 |
| 切り上げ | 小数部分があれば上の整数へ進める | 12.1 → 13 |
C#では、主に次のメソッドを使います。
| 処理 | メソッド |
|---|---|
| 切り捨て | Math.Truncate または Math.Floor |
| 四捨五入 | Math.Round |
| 切り上げ | Math.Ceiling |
目的に合わないメソッドを使うと、1円単位、1ポイント単位、1件単位の差が発生することがあります。
6-2. Math.Roundで四捨五入する方法
Math.Round は、数値を指定した桁数に丸めるメソッドです。
C#decimal value = 12.345m;
Console.WriteLine(Math.Round(value, 2)); // 12.34
ただし、C#の Math.Round は、標準では「銀行丸め」と呼ばれる偶数丸めを行います。
C#Console.WriteLine(Math.Round(2.5)); // 2
Console.WriteLine(Math.Round(3.5)); // 4
一般的な「0.5以上は切り上げ」にしたい場合は、MidpointRounding.AwayFromZero を指定します。
C#Console.WriteLine(Math.Round(2.5, MidpointRounding.AwayFromZero)); // 3
Console.WriteLine(Math.Round(3.5, MidpointRounding.AwayFromZero)); // 4
小数第2位まで四捨五入する場合は次のように書きます。
C#decimal value = 12.345m;
decimal result = Math.Round(value, 2, MidpointRounding.AwayFromZero);
Console.WriteLine(result); // 12.35
Math.Round は指定した小数桁数に丸めるメソッドで、既定では中間値を最も近い偶数へ丸める仕様があります。
6-3. Math.Ceilingで切り上げる方法
Math.Ceiling は、指定した数以上の最小の整数を返すメソッドです。
C#Console.WriteLine(Math.Ceiling(12.1)); // 13
Console.WriteLine(Math.Ceiling(12.9)); // 13
Console.WriteLine(Math.Ceiling(-12.1)); // -12
正の数では、小数部分があれば次の整数になります。
12.1 → 13
負の数では、0に近づく方向になる場合があります。
-12.1 → -12
Math.Ceiling は正の無限大方向への丸めです。Microsoft公式ドキュメントでも、指定した数以上の最小の整数を返すメソッドとして説明されています。
6-4. 目的別に使うべきメソッドの選び方
| 目的 | 使うメソッド |
|---|---|
| 小数部分を削除したい | Math.Truncate |
| 常に元の値以下の整数にしたい | Math.Floor |
| 常に元の値以上の整数にしたい | Math.Ceiling |
| 四捨五入したい | Math.Round |
| 小数第2位まで残して切り捨てたい | Math.Truncate(value * 100) / 100 |
| 金額を扱いたい | decimal 型と Math.Truncate |
単に「丸める」と言っても、切り捨て、切り上げ、四捨五入では意味が異なります。
仕様書や要件に「端数処理」と書かれている場合は、どの丸め方式なのかを必ず確認しましょう。
7. C#で切り捨てを使うときの注意点
7-1. 負の数ではTruncateとFloorの結果が変わる
もっとも重要な注意点は、負の数で Math.Truncate と Math.Floor の結果が変わることです。
C#decimal value = -1.9m;
Console.WriteLine(Math.Truncate(value)); // -1
Console.WriteLine(Math.Floor(value)); // -2
次のように、差額や補正値を扱う処理では負の値が発生することがあります。
C#decimal difference = actualAmount - expectedAmount;
このような値に対して切り捨てを行う場合、Math.Truncate と Math.Floor のどちらが正しいかは業務要件によって変わります。
「小数部分を消す」なら Math.Truncate。
「必ず元の値以下にする」なら Math.Floor。
この違いを曖昧にしないことが大切です。
7-2. double型の誤差に注意する
double 型は高速で便利ですが、10進数を正確に表せないことがあります。
C#double value = 0.1 + 0.2;
Console.WriteLine(value); // 0.30000000000000004 になることがある
このような誤差がある状態で切り捨てを行うと、期待と違う結果になる場合があります。
C#double value = 1.999999999999;
Console.WriteLine(Math.Truncate(value)); // 1
本来は2に近い値のつもりでも、内部的にわずかに小さい値になっていると、切り捨て結果が想定と変わることがあります。
金額、税、請求、精算などの処理では double ではなく decimal を使いましょう。
7-3. 金額計算ではdecimal型を使う
金額計算では、基本的に decimal 型を使います。
C#decimal price = 1000m;
decimal rate = 0.08m;
decimal tax = Math.Truncate(price * rate);
Console.WriteLine(tax); // 80
double で金額を扱うと、小数誤差の影響を受ける可能性があります。
C#double price = 1000;
double rate = 0.08;
double tax = Math.Truncate(price * rate);
単純な例では問題が見えにくいですが、計算回数が増えたり、小数点以下の桁数が多くなったりすると、誤差が蓄積することがあります。
金額計算では次のように書く習慣を付けると安全です。
C#decimal price = 1000m;
decimal rate = 0.08m;
7-4. キャストによる切り捨ては可読性に注意する
次のコードは小数部分を削除できます。
C#int result = (int)value;
しかし、このコードだけを見ると、「切り捨てをしたい」のか「整数型に変換したい」のかが分かりにくい場合があります。
意図を明確にするなら、次のように書くほうが親切です。
C#int result = (int)Math.Truncate(value);
また、int の範囲を超える値を変換しようとすると問題になります。
C#decimal value = 999999999999m;
// intの範囲を超えるため危険
// int result = (int)value;
整数型へ変換する場合は、値の範囲にも注意しましょう。
7-5. 桁数指定では10の累乗を正しく扱う
小数桁を指定して切り捨てる場合、10の累乗を使います。
C#decimal result = Math.Truncate(value * 100m) / 100m;
ここで、残したい桁数と掛ける値を間違えると結果が変わります。
| 残したい小数桁 | 掛ける値 |
|---|---|
| 0桁 | 1 |
| 1桁 | 10 |
| 2桁 | 100 |
| 3桁 | 1000 |
小数第2位まで残したいのに10を掛けると、小数第1位までしか残りません。
C#decimal value = 12.345m;
decimal wrong = Math.Truncate(value * 10m) / 10m;
decimal correct = Math.Truncate(value * 100m) / 100m;
Console.WriteLine(wrong); // 12.3
Console.WriteLine(correct); // 12.34
メソッド化して、桁数の指定ミスを減らすのがおすすめです。
8. よくあるエラー・つまずきポイント
8-1. Math.Truncateで期待した桁数にならない
Math.Truncate は、小数点以下をすべて削除するメソッドです。
そのため、次のように書いても小数第2位まで残すことはできません。
C#decimal value = 12.345m;
decimal result = Math.Truncate(value);
Console.WriteLine(result); // 12
小数第2位まで残したい場合は、100を掛けてから切り捨てます。
C#decimal value = 12.345m;
decimal result = Math.Truncate(value * 100m) / 100m;
Console.WriteLine(result); // 12.34
Math.Truncate 単体では桁数指定ができない、という点を覚えておきましょう。
8-2. Math.Floorで負の数の結果が想定と違う
次のコードで -1 になると思っていたのに、実際には -2 になります。
C#double value = -1.2;
double result = Math.Floor(value);
Console.WriteLine(result); // -2
これは Math.Floor が負の無限大方向へ丸めるためです。
小数部分を単純に削除したい場合は、Math.Truncate を使います。
C#double value = -1.2;
double result = Math.Truncate(value);
Console.WriteLine(result); // -1
負の数が入る可能性がある処理では、Floor を安易に「切り捨て」として使わないようにしましょう。
8-3. int型に変換すると小数部分が消える理由
double や decimal を int にキャストすると、小数部分は保持できません。
C#double value = 123.456;
int result = (int)value;
Console.WriteLine(result); // 123
これは、int 型が小数を表せない整数型だからです。
ただし、これは「表示上だけ小数が消えた」のではなく、値そのものが整数になっています。
C#int result = (int)123.456;
Console.WriteLine(result); // 123
小数部分を残したい場合は、int に変換してはいけません。
C#decimal result = Math.Truncate(123.456m * 100m) / 100m;
Console.WriteLine(result); // 123.45
8-4. 表示上の桁数と計算結果の桁数を混同している
ToString を使うと、表示形式を変えることができます。
C#decimal value = 12.3m;
Console.WriteLine(value.ToString("0.00")); // 12.30
ただし、これは値そのものを変えているわけではありません。
表示上は 12.30 になっても、数値としての値は 12.3m のままです。
逆に、次のように表示形式を指定しても、切り捨て処理にはなりません。
C#decimal value = 12.345m;
Console.WriteLine(value.ToString("0.00")); // 12.35 になる場合がある
書式指定は丸めを伴うことがあるため、「切り捨て」とは別物です。
値そのものを切り捨てたい場合は、計算で切り捨てを行いましょう。
C#decimal value = 12.345m;
decimal truncated = Math.Truncate(value * 100m) / 100m;
Console.WriteLine(truncated.ToString("0.00")); // 12.34
8-5. ToStringの書式指定では値自体は切り捨てられない
ToString("0.00") は、あくまで文字列としての表示形式を指定するものです。
C#decimal value = 12.349m;
string text = value.ToString("0.00");
Console.WriteLine(text); // 12.35 になる場合がある
この結果を見て「切り捨てできていない」と感じることがありますが、そもそも ToString は切り捨て用の処理ではありません。
切り捨ててから表示する場合は、次のように分けて考えます。
C#decimal value = 12.349m;
decimal truncated = Math.Truncate(value * 100m) / 100m;
string text = truncated.ToString("0.00");
Console.WriteLine(text); // 12.34
値を変える処理と、表示形式を整える処理は別です。
この2つを混同しないようにしましょう。
9. C#の切り捨てに関するよくある質問
9-1. C#で小数点以下を切り捨てるにはどのメソッドを使うべきか
小数部分を単純に取り除きたい場合は、Math.Truncate を使うのが分かりやすいです。
C#decimal value = 123.456m;
decimal result = Math.Truncate(value);
Console.WriteLine(result); // 123
正の数だけを扱うなら Math.Floor でも同じ結果になることが多いですが、負の数では違いが出ます。
C#Console.WriteLine(Math.Truncate(-123.456m)); // -123
Console.WriteLine(Math.Floor(-123.456m)); // -124
そのため、「小数点以下を消したい」という目的なら、基本的には Math.Truncate を選ぶとよいでしょう。
9-2. Math.Truncateとintキャストの違いは何か
Math.Truncate は小数部分を削除しますが、戻り値は decimal または double です。
C#decimal value = 123.456m;
decimal result = Math.Truncate(value);
一方、int キャストは小数部分を削除したうえで、値を int 型に変換します。
C#decimal value = 123.456m;
int result = (int)value;
違いをまとめると次のとおりです。
| 比較項目 | Math.Truncate | intキャスト |
|---|---|---|
| 主な目的 | 小数部分の削除 | 整数型への変換 |
| 戻り値 | decimal または double | int |
| 意図の分かりやすさ | 切り捨てと分かりやすい | 型変換に見える |
| 範囲外のリスク | 整数型変換しなければ低い | int 範囲外に注意 |
切り捨ての意図を明確にしたい場合は、Math.Truncate を使うのがおすすめです。
9-3. 小数第2位まで残して切り捨てるにはどうすればよいか
小数第2位まで残して切り捨てるには、100を掛けてから切り捨て、最後に100で割ります。
C#decimal value = 12.3456m;
decimal result = Math.Truncate(value * 100m) / 100m;
Console.WriteLine(result); // 12.34
再利用するならメソッド化します。
C#static decimal TruncateDecimal(decimal value, int decimalPlaces)
{
decimal factor = 1m;
for (int i = 0; i < decimalPlaces; i++)
{
factor *= 10m;
}
return Math.Truncate(value * factor) / factor;
}
使い方は次のとおりです。
C#decimal value = 12.3456m;
decimal result = TruncateDecimal(value, 2);
Console.WriteLine(result); // 12.34
9-4. 負の数を切り捨てる場合はどちらを使うべきか
負の数を扱う場合は、要件によって Math.Truncate と Math.Floor を使い分けます。
小数部分を単純に取り除きたい場合は Math.Truncate です。
C#Console.WriteLine(Math.Truncate(-1.9m)); // -1
常に元の値以下にしたい場合は Math.Floor です。
C#Console.WriteLine(Math.Floor(-1.9m)); // -2
「切り捨て」という言葉だけでは、どちらが正しいか判断できない場合があります。
負の数があり得る処理では、仕様として「0方向」なのか「負の無限大方向」なのかを確認しましょう。
9-5. 金額計算で安全に切り捨てるにはどうすればよいか
金額計算では、decimal 型を使い、Math.Truncate で切り捨てるのが基本です。
C#decimal price = 999m;
decimal taxRate = 0.10m;
decimal tax = Math.Truncate(price * taxRate);
Console.WriteLine(tax); // 99
小数第2位まで残す場合は、桁数指定の切り捨てを使います。
C#decimal amount = 123.456m;
decimal result = Math.Truncate(amount * 100m) / 100m;
Console.WriteLine(result); // 123.45
金額計算では、次の点に注意してください。
| 注意点 | 内容 |
|---|---|
| 型 | double ではなく decimal を使う |
| リテラル | 100.5m のように m を付ける |
| 端数処理 | 切り捨て、四捨五入、切り上げを明確にする |
| 負の値 | Truncate と Floor の違いを確認する |
| 表示 | ToString は表示形式であり、値の切り捨てではない |
税額、請求額、割引額、返金額などは1円の差が問題になることもあるため、端数処理のルールを明確に実装しましょう。
まとめ
C#で切り捨てを行う方法は複数ありますが、基本は Math.Truncate と Math.Floor の違いを理解することです。
小数部分を単純に削除したい場合は、Math.Truncate を使います。
C#decimal result = Math.Truncate(12.345m); // 12
常に元の値以下の整数にしたい場合は、Math.Floor を使います。
C#decimal result = Math.Floor(-12.345m); // -13
小数第2位まで残して切り捨てる場合は、10の累乗を使います。
C#decimal value = 12.3456m;
decimal result = Math.Truncate(value * 100m) / 100m;
Console.WriteLine(result); // 12.34
金額計算では decimal 型を使いましょう。
C#decimal price = 999m;
decimal taxRate = 0.10m;
decimal tax = Math.Truncate(price * taxRate);
最後に、使い分けを整理します。
| やりたいこと | 使う方法 |
|---|---|
| 小数点以下を切り捨てたい | Math.Truncate |
| 元の値以下の整数にしたい | Math.Floor |
| 整数型に変換したい | int などへキャスト |
| 小数第2位まで残したい | Math.Truncate(value * 100) / 100 |
| 四捨五入したい | Math.Round |
| 切り上げたい | Math.Ceiling |
| 金額計算したい | decimal 型を使う |
C#の切り捨ては、正の数だけなら簡単に見えますが、負の数、金額、桁数指定、表示形式が絡むと注意点が増えます。
Math.Truncate、Math.Floor、Math.Round、Math.Ceiling の違いを理解し、目的に合ったメソッドを選ぶことが、正確で読みやすいコードを書くためのポイントです。

