HOWTO · Csharp

C# で decimal を int に変換する

C# で decimal を int に変換する際に、切り捨て、丸め、方向指定の丸めを選び、Int32 の範囲外の値を扱う方法を説明します。

このページの内容

端数を捨てるなら (int)value を使います。最も近い整数に丸めるなら Convert.ToInt32(value) を使い、方向を指定した丸めや特定の中間値規則が必要なら Math メソッドを使います。次の簡潔な例では、正の値に対するこれらの選択肢を比較しています。

using System;

class Program
{
    static void Main()
    {
        decimal value = 12.9m;
        Console.WriteLine("cast: " + (int)value);
        Console.WriteLine("nearest: " + Convert.ToInt32(12.5m) + ", " + Convert.ToInt32(13.5m));
        Console.WriteLine("floor: " + Math.Floor(value));
        Console.WriteLine("ceiling: " + Math.Ceiling(value));
        Console.WriteLine("away: " + Math.Round(2.5m, MidpointRounding.AwayFromZero));
    }
}
cast: 12
nearest: 12, 14
floor: 12
ceiling: 13
away: 3

変換の方針は表示上の細部ではなく、業務上の規則です。金額や測定値のように小数部分が意味を持つ場合は、値を decimal のまま保持してください。最終的に int へ変換する場合は、Int32 に収まらない値も考慮する必要があります。

decimal をゼロ方向に切り捨てる

切り捨てには、明示的キャスト (int)value が最も分かりやすい選択です。decimal リテラルには m 接尾辞が必要です。接尾辞がない 12.9 のようなリテラルは double になります。decimal から整数型への変換はゼロ方向に丸めるため、(int)12.9m は 12、(int)-12.9m は -12 になります。これは floor でも ceiling でもありません。C# の数値変換リファレンス に、ゼロ方向への動作と範囲外の場合の失敗が記載されています。

最も近い整数に丸める

Convert.ToInt32(decimal) は切り捨てではなく、最も近い 32 ビット符号付き整数に丸めます。小数部分がちょうど .5 の場合は中間値を偶数へ丸めるため、Convert.ToInt32(12.5m) は 12、Convert.ToInt32(13.5m) は 14 になります。最も近い整数単位にそろえたい測定値には便利ですが、すべての中間値をゼロから離れる方向へ動かしたい場合には適した規則ではありません。

Convert.ToInt32 の decimal オーバーロードのドキュメントでは、int の範囲外の値に対して OverflowException が指定されています。このメソッドを使っても、範囲を超えた decimal が安全になるわけではありません。

明示的な丸め規則を選ぶ

方向を指定した丸めでは、まず decimal に Math メソッドを適用し、その結果を整数型へ変換します。Math.Floor は負の無限大方向へ進むため、Math.Floor(-12.9m) は -13m になります。一方、Math.Ceiling は正の無限大方向へ進みます。そのため、どちらも -12.9m を -12 にする (int)-12.9m とは異なります。

最近接丸めで中間値の規則を明示するには、Math.Round(value, MidpointRounding.AwayFromZero) を使います。これにより 2.5m は 3m、-2.5m は -3m になります。Math.Round(decimal) の既定値は中間値を偶数へ丸めます。Math.Truncateも、int に変換する前にゼロ方向の整数値を持つ decimal を得る、読みやすい方法です。

丸める前にキャストしてはいけません。(int)value を実行した時点で端数はすでに失われているため、その後で Math.Round を呼び出しても意図した選択を復元できません。先に丸め、結果を確認してからキャストしてください。

int 範囲外の値を扱う

int は int.MinValue から int.MaxValue までの範囲を持つ 32 ビット符号付き整数です。Int32 は対応するフレームワーク型です。decimal はこれらの境界を超える値も表現できます。decimal から int への変換では、結果が範囲外になると OverflowException が発生します。値が端点に自動的に制限されることはありません。

範囲外の入力があり得る場合は、変換前に値を検証するか、アプリケーションの境界で OverflowException を捕捉してください。checked 変換は意図を明示し、範囲に関する契約のテストに役立ちますが、decimal から int への変換でオーバーフローを検出する仕組みそのものではありません。受け側の契約で許されるなら、値を decimal のまま保持するか、より広い整数型を選び、無理に int へ押し込まないでください。

規則に合う変換を選ぶ

意図した結果 使用方法 重要な動作
端数を捨てる (int)value ゼロ方向に切り捨てます。
最も近い int Convert.ToInt32(value) 中間値は偶数へ丸めます。
常に小さい値または大きい値 Math.Floor または Math.Ceiling の後にキャスト 負数では、方向指定の丸めは切り捨てと異なります。
独自の中間値規則 MidpointRounding を指定した Math.Round の後にキャスト 同値の場合の規則を明示します。

通常の切り捨てには明示的キャストを選びます。アプリケーションが必要とする丸め規則に合う場合だけ Convert.ToInt32 や Math メソッドを使い、int の境界では OverflowException を処理してください。