HOWTO · Csharp

在 C# 中將 decimal 轉換為 int

說明在 C# 中將 decimal 轉換為 int 時,如何選擇截斷、四捨五入或定向捨入規則,並處理超出 Int32 範圍的值。

本頁內容

在 C# 中將 decimal 轉換為 int 時,如果要捨棄小數部分,請使用明確的型別轉換;如果要取得最接近的整數,請使用 Convert.ToInt32。如果需要固定無條件捨去、無條件進位或指定的中點規則,請先依該規則捨入,再進行型別轉換。如果值超出 Int32 範圍,任何轉換都可能引發 OverflowException。

這不是顯示格式問題,而是業務規則。例如,-12.9m 截斷後是 -12,使用 Math.Floor 無條件捨去後是 -13。如果金額或測量值的小數部分仍然重要,請保留 decimal 型別。

將 decimal 朝零截斷

如果目標是截斷,(int)value 能清楚表達意圖。decimal 常值需要 m 後綴;沒有後綴的 12.9 是 double。整數轉換會朝零進行,而不是使用 floor 或 ceiling 規則。請參閱 C# numeric conversions。

using System;

decimal positive = 12.9m;
decimal negative = -12.9m;
Console.WriteLine($"cast: {(int)positive}, {(int)negative}");
Console.WriteLine($"round: {Convert.ToInt32(12.5m)}, {Convert.ToInt32(13.5m)}");
try
{
    decimal tooLarge = decimal.MaxValue;
    Console.WriteLine(checked((int)tooLarge));
}
catch (OverflowException)
{
    Console.WriteLine("overflow");
}
cast: 12, -12
round: 12, 14
overflow

第一行輸出展示捨棄小數部分並讓負數朝零靠近的行為。最後一行是邊界範例。checked 讓溢位行為明確,並透過 catch 回報問題,而不是讓程式終止。

捨入到最接近的整數

Convert.ToInt32(decimal) 不是截斷,而是捨入到最接近的 32 位元帶正負號整數;小數部分恰好為 .5 時使用中點向偶數捨入。在已驗證的範例中,12.5m 變成 12,13.5m 變成 14。

只有當應用程式確實需要中點向偶數捨入時,才應選擇 Convert.ToInt32。decimal 多載文件同樣說明超出範圍時會引發 OverflowException。

選擇明確的捨入規則

對於定向捨入,應先對 decimal 套用 Math 方法。Math.Floor 朝負無限大移動,Math.Ceiling 朝正無限大移動,因此 Math.Floor(-12.9m) 是 -13m,而 (int)-12.9m 是 -12。

如果需要不同的中點規則,請在程式碼中明確寫出。Math.Round(value, MidpointRounding.AwayFromZero) 會將 2.5m 變成 3m,將 -2.5m 變成 -3m。相反地,預設的 Math.Round(decimal) 使用中點向偶數捨入。Math.Truncate 也是取得朝零整數化 decimal 的清楚選擇。

不要先進行型別轉換。(int)value 已經遺失小數部分,之後再呼叫 Math.Round 無法恢復原本的捨入意圖。應先捨入,確認結果在範圍內,再進行型別轉換。

處理超出 int 範圍的值

int 是範圍從 int.MinValue 到 int.MaxValue 的 32 位元帶正負號整數。decimal 可以表示遠超過這個範圍的值。直接轉換超出範圍的值會引發 OverflowException,不會自動將值限制到最近的端點。

如果預期輸入可能超出範圍,請在轉換前驗證,或在應用程式邊界捕捉 OverflowException。不要為了配合 API 而靜默轉換金額;如果契約允許,請選擇更寬的整數型別或繼續使用 decimal。

選擇符合規則的轉換

目標結果 使用方式 重要行為
捨棄小數部分 (int)value 朝零截斷。
最接近的 int Convert.ToInt32(value) 中點向偶數捨入。
始終向下或向上 Math.Floor 或 Math.Ceiling 後再轉換 對負數而言不同於截斷。
自訂中點規則 使用 MidpointRounding 的 Math.Round 後再轉換 明確寫出捨入規則。

對於普通截斷,明確的型別轉換是簡潔的選擇。只有需要特定捨入規則時才使用 Convert.ToInt32 或 Math 方法,並始終處理 int 邊界上的 OverflowException。