共用方式為


算術運算子 (C# 參考)

下列運算子會使用數值類型的運算元來執行算術運算:

所有 整數浮點 數類型都支援這些運算符。

intuintlongulong 類型會定義所有這些運算子。 其他整數型別(sbytebyteshortushortchar)只定義 ++-- 運算子。 對於其他運算子,若使用整數型別 、 、 short或 作為運算元,值會轉換為 型int態,結果型態為 intcharushortbytesbyte 若操作數為不同的整數或浮點型態,則其值會轉換成最接近的包含型別(若存在)。 如需詳細資訊,請參閱 C# 語言規格數值升階一節。 ++-- 運算子是針對所有整數和浮點數值類型以及 char 類型所定義。 複合指派運算式的結果類型是左側運算元的類型。

C# 語言參考資料記錄了 C# 語言最新版本。 同時也包含即將推出語言版本公開預覽功能的初步文件。

文件中標示了語言最近三個版本或目前公開預覽版中首次引入的任何功能。

小提示

欲查詢某功能何時首次在 C# 中引入,請參閱 C# 語言版本歷史的條目。

遞增運算子 ++

一元遞增運算子 ++ 的運算元遞增量為 1。 運算元必須是變數、屬性存取或索引子存取。

遞增運算子支援兩種形式:後置遞增運算子 x++ 和前置遞增運算子 ++x

後置遞增運算子

x++ 的結果為運算「之前」x 值,如下列範例所示:

int i = 3;
Console.WriteLine(i);   // output: 3
Console.WriteLine(i++); // output: 3
Console.WriteLine(i);   // output: 4

前置遞增運算子

++x 的結果為運算「之後」x 值,如下列範例所示:

double a = 1.5;
Console.WriteLine(a);   // output: 1.5
Console.WriteLine(++a); // output: 2.5
Console.WriteLine(a);   // output: 2.5

遞減運算子 --

一元遞減運算子 (--) 的運算元遞減量為 1。 運算元必須是變數、屬性存取或索引子存取。

遞減運算子有兩種形式:後綴遞減運算子,x--以及前綴遞減運算子。 --x

後置遞減運算子

x-- 的結果為運算「之前」x 值,如下列範例所示:

int i = 3;
Console.WriteLine(i);   // output: 3
Console.WriteLine(i--); // output: 3
Console.WriteLine(i);   // output: 2

前置遞減運算子

--x 的結果為運算「之後」x 值,如下列範例所示:

double a = 1.5;
Console.WriteLine(a);   // output: 1.5
Console.WriteLine(--a); // output: 0.5
Console.WriteLine(a);   // output: 0.5

一元加號和減號運算子

一元 + 運算子會傳回其運算元的值。 一元 - 運算子會計算其運算元的負數值。

Console.WriteLine(+4);     // output: 4

Console.WriteLine(-4);     // output: -4
Console.WriteLine(-(-4));  // output: 4

uint a = 5;
var b = -a;
Console.WriteLine(b);            // output: -5
Console.WriteLine(b.GetType());  // output: System.Int64

Console.WriteLine(-double.NaN);  // output: NaN

一元 運算子不支援 - 類型。

乘法運算子 *

乘法運算子 * 會計算其運算元的乘積:

Console.WriteLine(5 * 2);         // output: 10
Console.WriteLine(0.5 * 2.5);     // output: 1.25
Console.WriteLine(0.1m * 23.4m);  // output: 2.34

一元 * 運算子是一個指標間接運算子

除法運算子 /

除法運算子 / 會將它的左邊運算元除以右邊運算元。

整數除數

對於整數型運算元,算符的結果 / 為整數型,且等於兩個運算元四捨五入後的商:

Console.WriteLine(13 / 5);    // output: 2
Console.WriteLine(-13 / 5);   // output: -2
Console.WriteLine(13 / -5);   // output: -2
Console.WriteLine(-13 / -5);  // output: 2

要得到兩個運算元的商運算數為浮點數,請使用 floatdoubledecimal 類型:

Console.WriteLine(13 / 5.0);       // output: 2.6

int a = 13;
int b = 5;
Console.WriteLine((double)a / b);  // output: 2.6

浮點除數

對於 floatdoubledecimal 類型, / 算符回傳兩個運算元的商運算元:

Console.WriteLine(16.8f / 4.1f);   // output: 4.097561
Console.WriteLine(16.8d / 4.1d);   // output: 4.09756097560976
Console.WriteLine(16.8m / 4.1m);   // output: 4.0975609756097560975609756098

若其中一個運算元為 decimal,另一個操作數則無法是 floatdouble,因為兩者floatdouble皆不包含轉換為 decimal。 您必須明確地將 floatdouble 運算元轉換為 decimal 型別。 如需在數值類型之間進行轉換的詳細資訊,請參閱內建數值轉換

餘數運算子 %

餘數運算子 % 會計算其左邊運算元除以右邊運算元之後的餘數。

整數餘數

對於整數型態的運算元,的 a % b 結果是由 $a - \frac{a}{b} \times b$ 所產生的值。 非零餘數的符號與左手運算元的符號相符,如下範例所示:

Console.WriteLine(5 % 4);   // output: 1
Console.WriteLine(5 % -4);  // output: 1
Console.WriteLine(-5 % 4);  // output: -1
Console.WriteLine(-5 % -4); // output: -1

使用 Math.DivRem 方法計算整數除法和餘數結果。

浮點數餘數

對於 floatdouble 運算元,有限 x % yxy 結果是 z 值,像是

  • 若 非零,則 的 z符號與 的 x符號相符。
  • z 絕對值來自計算 $|x| - n \times |y|$,其中 n 是小於或等於 $\frac{|x|} 的最大整數{|y|}$. 此處,$|x|$ 與 $|y|$ 分別代表 與 yx絕對值。

注意

此計算餘數的方法類似整數運算元,但與 IEEE 754 規範不同。 如果您需要符合 IEEE 754 規格的餘數運算,則請使用 Math.IEEERemainder 方法。

如需在非有限運算元情況中 % 運算子的行為,請參閱 C# 語言規格餘數運算子小節。

對於decimal運算元,剩餘運算子%的運作方式與該System.Decimal類型的剩餘運算子相同。

以下範例展示了剩餘運算子在浮點運算元下的行為:

Console.WriteLine(-5.2f % 2.0f); // output: -1.2
Console.WriteLine(5.9 % 3.1);    // output: 2.8
Console.WriteLine(5.9m % 3.1m);  // output: 2.8

加法運算子 +

加法運算子 + 會計算其運算元的總和:

Console.WriteLine(5 + 4);       // output: 9
Console.WriteLine(5 + 4.3);     // output: 9.3
Console.WriteLine(5.1m + 4.2m); // output: 9.3

您也可以使用 + 運算子來進行字串串連和委派合併。 如需詳細資訊,請參閱 ++= 運算子一文。

減法運算子 -

減法運算子 - 是從左操作數中減去右手運算子:

Console.WriteLine(47 - 3);      // output: 44
Console.WriteLine(5 - 4.3);     // output: 0.7
Console.WriteLine(7.5m - 2.3m); // output: 5.2

你也可以用操作 - 員移除代理人。 欲了解更多資訊,請參閱-=運算子。-

複合指派

若是二元運算子 op,表單的複合指派運算式

x op= y

相當於

x = x op y

唯一不同的是 x 只會被評估一次。

下列範例示範如何搭配算術運算子使用複合指派:

int a = 5;
a += 9;
Console.WriteLine(a);  // output: 14

a -= 4;
Console.WriteLine(a);  // output: 10

a *= 2;
Console.WriteLine(a);  // output: 20

a /= 4;
Console.WriteLine(a);  // output: 5

a %= 3;
Console.WriteLine(a);  // output: 2

由於數值升變,操作結果op可能無法隱含轉換為 的類型Tx。 在此情況下,如果 op 是預先定義的運算子,且作業結果可以明確轉換成 Tx 型別,則形式 x op= y 的複合指派運算式相等於 x = (T)(x op y),唯一的不同在於 x 只會評估一次。 下列範例示範了該行為:

byte a = 200;
byte b = 100;

var c = a + b;
Console.WriteLine(c.GetType());  // output: System.Int32
Console.WriteLine(c);  // output: 300

a += b;
Console.WriteLine(a);  // output: 44

在上述範例中,值 44 是將值 300 轉換成 byte 型別的結果。

注意

已檢查的溢位檢查內容中,上述範例會擲回 OverflowException。 如需詳細資訊,請參閱整數算術溢位一節。

您也可以使用 +=-= 運算子,來分別訂閱和取消訂閱事件。 如需詳細資訊,請參閱如何訂閱及取消訂閱事件

運算子優先順序和關聯性

以下列表將算術運算子從最高優先順序排列至最低優先順序:

  • 後置遞增 x++ 和遞減 x-- 運算子
  • 前綴、遞增 ++x 與遞減 --x 運算子,以及一元 +- 運算元
  • 乘法類 */% 運算子
  • 加法類 +- 運算子

二元算術運算子都是左向關聯。 也就是說,編譯器會從左到右評估具有相同優先順序的運算子。

使用括號 () 變更運算子優先順序和關聯性強制執行的評估順序。

Console.WriteLine(2 + 2 * 2);   // output: 6
Console.WriteLine((2 + 2) * 2); // output: 8

Console.WriteLine(9 / 5 / 2);   // output: 0
Console.WriteLine(9 / (5 / 2)); // output: 4

如需依優先順序層級排序的 C# 運算子完整清單,請參閱 C# 運算子一文的運算子優先順序一節。

算術溢位和除數為零

當算術運算的結果超出可能相關數字型別有限值的範圍之外時,算術運算子的行為取決於其運算元的型別。

整數算術溢位

整數除以零一定會擲回 DivideByZeroException

如果發生整數算術溢位,則溢位檢查內容 (可以是 checked 或 unchecked) 可控制所產生的行為:

  • 在 checked 內容中,如果常數運算式發生溢位,則會發生編譯時期錯誤。 否則,當運算是在執行階段執行時,就會擲回 OverflowException
  • 在 unchecked 內容中,會捨棄目的型別不適用的高序位位元,以便將結果截斷。

注意

整數除法有一個特殊情況,即即使在未檢查的情境中也可能拋出 。ArithmeticException 當左操作數是帶符號整數類型的最小值(int.MinValuelong.MinValue),而右操作數為 -1時,結果無法以目的類型表示。 .NET 執行時在此情況下拋出 , ArithmeticException 如下範例所示:

int a = int.MinValue;
int b = -1;
try
{
    int c = unchecked(a / b);
}
catch (ArithmeticException)
{
    Console.WriteLine($"Overflow occurred when dividing {a} by {b}.");
}

除了 checked 與 unchecked 陳述式之外,您還可以使用 checkedunchecked 運算子來控制評估運算式的溢位檢查內容:

int a = int.MaxValue;
int b = 3;

Console.WriteLine(unchecked(a + b));  // output: -2147483646
try
{
    int d = checked(a + b);
}
catch(OverflowException)
{
    Console.WriteLine($"Overflow occurred when adding {a} to {b}.");
}

根據預設,unchecked 內容中會發生算術運算。

浮點算術溢位

利用 floatdouble 型別進行算術運算時,絕不會拋出例外。 使用這些類型進行算術運算的結果可以是代表無限大且非數字的特殊值:

double a = 1.0 / 0.0;
Console.WriteLine(a);                    // output: Infinity
Console.WriteLine(double.IsInfinity(a)); // output: True

Console.WriteLine(double.MaxValue + double.MaxValue); // output: Infinity

double b = 0.0 / 0.0;
Console.WriteLine(b);                // output: NaN
Console.WriteLine(double.IsNaN(b));  // output: True

針對 decimal 類型的運算元,算術溢位一律會擲回 OverflowException。 除數為零一律會擲回 DivideByZeroException

四捨五入錯誤

由於實數浮點表示和浮點運算的一般限制,使用浮點類型的計算中可能會發生捨入誤差。 某個表達式的結果可能與預期的數學結果不同。 下列範例將示範幾個這類案例:

Console.WriteLine(.41f % .2f); // output: 0.00999999

double a = 0.1;
double b = 3 * a;
Console.WriteLine(b == 0.3);   // output: False
Console.WriteLine(b - 0.3);    // output: 5.55111512312578E-17

decimal c = 1 / 3.0m;
decimal d = 3 * c;
Console.WriteLine(d == 1.0m);  // output: False
Console.WriteLine(d);          // output: 0.9999999999999999999999999999

欲了解更多資訊,請參閱 System.DoubleSystem.SingleSystem.Decimal 參考頁面的備註。

運算子是否可多載

你可以對使用者定義型別的一元++(, --+, , 和-)和二元/+*%(, 和-)算術運算子進行超載。 當你超載一個二元運算子時,也會隱含地讓對應的複合指派運算子超載。 從 C# 14 開始,使用者定義型別可以明確超載複合指派運算子(op=),以提供更有效率的實作。 一般而言,型別會多載這些運算符,因為值可以就地更新,而不是配置新的實例來儲存作業的結果。 如果類型未提供明確的多載,編譯程式會產生隱含多載。

使用者定義的 checked 運算子

當你超載算術運算子時,可以用關鍵字 checked 定義該運算子 的檢查版本 。 下列範例顯示如何執行該項工作:

public record struct Point(int X, int Y)
{
    public static Point operator checked +(Point left, Point right)
    {
        checked
        {
            return new Point(left.X + right.X, left.Y + right.Y);
        }
    }
    
    public static Point operator +(Point left, Point right)
    {
        return new Point(left.X + right.X, left.Y + right.Y);
    }
}

當您定義 checked 運算子時,也必須定義沒有 checked 修飾元的對應運算子。 檢查過的上下文呼叫檢查過的運算子,未檢查的上下文則呼叫未加checked修飾符的運算子。

當你定義兩個版本的運算子時,只有當運算結果過大無法以結果類型表示時,它們的行為才會有所不同:

  • checked 運算子擲回 OverflowException
  • 沒有 checked 修飾元的運算子會傳回代表 truncated 結果的執行個體。

如需內建算術運算子行為差異的相關資訊,請參閱算術溢位和除數為零一節。

只有在您多載下列任何運算子時,才能使用 checked 修飾元:

  • 一元 ++--- 運算子
  • 二元 */+- 運算子
  • 複合指派 *=/=+=-= 運算子 (C# 14 和更新版本)
  • 明確轉換運算子

注意

checked 飾符不會影響其主體內的溢位檢查上下文。 預設內容是由 CheckForOverflowUnderflow 編譯器選項的值所定義。 使用 checkedunchecked 陳述式明確地指定溢位檢查內容,如本節開頭的範例所示範。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格的下列幾節:

另請參閱