算術運算子是程式計算的基石。C# 提供五大運算子 (+, -, *, /, %),支援整數、浮點數、十進位數與使用者定義型別 (透過多載)。理解求值順序、溢位行為與餘數運算特性,對數值計算正確性至關重要。
| 運算子 | 名稱 | 元數 | 支援類型 |
|---|---|---|---|
+ | 加法 | 二元 | 數值、字串、委派、列舉、TimeSpan |
- | 減法 | 二元/一元 | 數值、委派、列舉、TimeSpan |
* | 乘法 | 二元 | 數值 |
/ | 除法 | 二元 | 數值 |
% | 餘數 | 二元 | 整數、浮點數、十進位數 |
C# 保證運算元與引數由左至右評估,無論運算子優先級:
static void F(int x, int y, int z)
=> Console.WriteLine($"x={x}, y={y}, z={z}");
int i = 0;
F(i++, i++, i++);
// 輸出:x=0, y=1, z=2
// 順序:第一個 i++ (值 0, i→1), 第二個 (值 1, i→2), 第三個 (值 2, i→3)
int a = 0; int result = a++ + a++ * a++; // 1. 左至右取值:0, 1, 2 // 2. 依優先級計算:0 + (1 * 2) = 2 // 3. 副作用已完成:a = 3
// a = (a / b) * b + (a % b) // 餘數符號與被除數 (a) 相同
5 % 3 // 2 -5 % 3 // -2 (被除數負,餘數負) 5 % -3 // 2 (被除數正,餘數正) -5 % -3 // -2
5.0 % 3.0 // 2.0 5.0 % 1.5 // 0.5 5.5m % 2.0m // 1.5m (decimal) double nan = double.NaN; nan % 2.0 // NaN double.PositiveInfinity % 2.0 // NaN
// 數學模:結果永遠非負 (Python 行為)
// C# 餘數:符號跟隨被除數
// 修正為非負模運算
int Mod(int a, int b)
{
int r = a % b;
return r < 0 ? r + Math.Abs(b) : r;
}
// Mod(-5, 3) = 1
| 語境 | 整數溢位行為 | 浮點數溢位 |
|---|---|---|
unchecked (預設) | 環繞 (截斷高位) | ±Infinity |
checked | 拋出 OverflowException | ±Infinity (不受影響) |
| 常數運算式 | 編譯時期檢查 (永遠 checked) | 編譯時期計算 |
// 預設 unchecked:環繞
int max = int.MaxValue;
var wrap = max + 1; // -2147483648 (int.MinValue)
// checked:拋出例外
checked
{
var crash = max + 1; // OverflowException
}
// 常數運算式永遠檢查
// const int crash = int.MaxValue + 1; // 編譯錯誤 CS0220
5 / 3 // 1 -5 / 3 // -1 (向零截斷,非向下取整) 5 / -3 // -1 -5 / -3 // 1
5.0 / 2.0 // 2.5 5.0 / 0.0 // Infinity -5.0 / 0.0 // -Infinity 0.0 / 0.0 // NaN
10.0m / 3.0m // 3.3333333333333333333333333333 (28-29 位有效數字) 1.0m / 0.0m // DivideByZeroException (decimal 無 Infinity/NaN)
+5 // 5 (無作用,僅為對稱性)
-5 // -5
-( -5) // 5
// 陷阱:最小值取負仍為最小值 (溢位)
int min = int.MinValue; // -2147483648
int neg = -min; // -2147483648 (環繞,unchecked)
checked { -min; } // OverflowException
public readonly struct Vector2
{
public double X, Y;
public static Vector2 operator +(Vector2 a, Vector2 b)
=> new Vector2 { X = a.X + b.X, Y = a.Y + b.Y };
public static Vector2 operator -(Vector2 a, Vector2 b)
=> new Vector2 { X = a.X - b.X, Y = a.Y - b.Y };
public static Vector2 operator *(Vector2 a, double k)
=> new Vector2 { X = a.X * k, Y = a.Y * k };
public static Vector2 operator /(Vector2 a, double k)
=> new Vector2 { X = a.X / k, Y = a.Y / k };
// 一元運算子
public static Vector2 operator -(Vector2 a)
=> new Vector2 { X = -a.X, Y = -a.Y };
}
decimal — 避免二進位浮點誤差double — 範圍大、硬體加速checked — 或 checked 區塊精通算術運算子的求值順序、溢位語境、餘數符號規則與除法細節,是編寫正確數值計算程式的基礎功力。