首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 乘法運算完整指南:整數/浮點數/decimal 溢位、精度與運算子多載模式

     編輯:關於C#

乘法運算 (*) 是數值計算的核心,但在不同類型上呈現不同的溢位、精度與效能特性。C# 對整數、浮點數、decimal 定義了精確語意,並支援使用者定義型別多載。理解這些細節,對科學計算、金融系統與高效能程式庫開發至關重要。

三大數值類型乘法語意對比

特性整數 (int, long...)浮點數 (float, double)decimal
溢位行為環繞 (unchecked) / 例外 (checked)±Infinity例外 (OverflowException)
精度精確 (範圍內)~15-17 位 (double)28-29 位有效數字
特殊值無±0.0, ±∞, NaN無
交換律成立成立 (NaN 除外)成立
結合律成立 (無溢位時)不成立 (捨入誤差)不成立 (捨入誤差)

整數乘法:溢位風險與檢查

溢位範例

int a = 50000, b = 50000;
int c = a * b; // 2,500,000,000 → 環繞為 -1794967296 (unchecked)

// checked 語境
checked 
{
    int d = a * b; // OverflowException
}

// 長整數避免溢位
long e = (long)a * b; // 2,500,000,000L (正確)

// 編譯時期常數檢查
// const int overflow = 50000 * 50000; // CS0220 編譯錯誤

乘法溢位檢測技巧

// 安全乘法:檢查是否溢位 (不使用 checked)
bool SafeMultiply(int a, int b, out int result)
{
    if (a == 0 || b == 0) { result = 0; return true; }
    if (a > 0)
    {
        if (b > 0) return a <= int.MaxValue / b ? (result = a * b, true) : false;
        return b >= int.MinValue / a ? (result = a * b, true) : false;
    }
    if (b > 0) return a >= int.MinValue / b ? (result = a * b, true) : false;
    return a != 0 && b >= int.MaxValue / a ? (result = a * b, true) : false;
}

// .NET 內建 (Core 2.0+)
bool ok = int.TryMultiply(a, b, out int result); // 不拋出例外,回傳是否成功

浮點數乘法:IEEE 754 特殊值語意

特殊值乘法表

×正常 > 0正常 < 0+0.0-0.0+∞-∞NaN
正常 > 0正常負正常+0.0-0.0+∞-∞NaN
正常 < 0負正常正常-0.0+0.0-∞+∞NaN
+0.0+0.0-0.0+0.0-0.0NaNNaNNaN
-0.0-0.0+0.0-0.0+0.0NaNNaNNaN
+∞+∞-∞NaNNaN+∞-∞NaN
-∞-∞+∞NaNNaN-∞+∞NaN
NaNNaNNaNNaNNaNNaNNaNNaN

關鍵屬性

// 0 × ∞ = NaN (不定式)
0.0 * double.PositiveInfinity // NaN

// 正負零
0.0 * -5.0  // -0.0
-0.0 * -5.0 // +0.0

// NaN 傳播
double.NaN * 5.0 // NaN

decimal 乘法:銀行家捨入、精確範圍

高精度範例

decimal a = 0.1m, b = 0.2m;
decimal c = a * b; // 0.02 (精確,無二進位誤差)

// 科學計數法
decimal d = 1.2345678901234567890123456789m;
decimal e = 9.8765432109876543210987654321m;
decimal f = d * e; // 12.193263111263526919530400125 (28-29 位)

溢位例外 (無 Infinity)

decimal max = decimal.MaxValue; // ~7.9e28
decimal two = 2.0m;

var crash = max * two; // OverflowException

// 檢查模式
decimal SafeMultiply(decimal a, decimal b)
{
    if (a == 0 || b == 0) return 0;
    if (decimal.Abs(a) > decimal.MaxValue / decimal.Abs(b))
        throw new OverflowException("Decimal 乘法溢位");
    return a * b;
}

列舉類型乘法 (實為加法語意)

注意:C# 列舉不支援乘法運算子。列舉僅支援:

  • E + U、U + E (加入基底值)
  • E - E (差值得基底型別)、E - U (減去基底值)
  • 比較運算子
enum Day { Mon=1, Tue=2, Wed=3 }
Day d = Day.Mon + 2; // Day.Wed (值 3)
// Day d2 = Day.Mon * 2; // 編譯錯誤:無乘法運算子

字串與委派:無乘法運算子

  • 字串:僅支援 + (串接)
  • 委派:僅支援 + (合併)、- (移除)

使用者定義型別多載標準模式

public readonly struct Matrix2x2
{
    public double M11, M12, M21, M22;
    
    // 矩陣乘法
    public static Matrix2x2 operator *(Matrix2x2 a, Matrix2x2 b) => new Matrix2x2
    {
        M11 = a.M11 * b.M11 + a.M12 * b.M21,
        M12 = a.M11 * b.M12 + a.M12 * b.M22,
        M21 = a.M21 * b.M11 + a.M22 * b.M21,
        M22 = a.M21 * b.M12 + a.M22 * b.M22
    };
    
    // 標量乘法
    public static Matrix2x2 operator *(Matrix2x2 m, double k) => new Matrix2x2
    {
        M11 = m.M11 * k, M12 = m.M12 * k,
        M21 = m.M21 * k, M22 = m.M22 * k
    };
    public static Matrix2x2 operator *(double k, Matrix2x2 m) => m * k; // 交換律
}

效能特性與優化

類型指令延遲 (週期)吞吐率 (週期/指令)向量化
int/long3-50.5-1SIMD (AVX2/AVX-512)
float4-50.5SIMD (4/8-wide)
double4-50.5SIMD (2/4-wide)
decimal~50-200~50無 (軟體模擬)

編譯器優化

// 常數摺疊
const int c = 5 * 10; // 編譯時期計算 = 50

// 強度削減:乘以 2 的冪次 → 位移
x * 2   → x << 1
x * 4   → x << 2
x * 8   → x << 3

// 乘以常數 → 移位加減組合 (編譯器自動)
x * 10  → (x << 3) + (x << 1)  // 8x + 2x
x * 15  → (x << 4) - x         // 16x - x

SIMD 向量化乘法

// System.Numerics.Vectors / System.Runtime.Intrinsics
Vector a = new Vector(arr1);
Vector b = new Vector(arr2);
Vector c = a * b; // 單指令 4/8 個 float 並行乘法

最佳實踐總結

  1. 整數乘法溢位風險高 — 熱路徑用 long 或 checked/TryMultiply
  2. 浮點數乘法注意 0×∞=NaN — 檢查特殊值傳播
  3. 金融計算必用 decimal — 精確捨入、無二進位誤差
  4. decimal 乘法慢 50-100x — 避免熱路徑,或用定點整數替代
  5. 矩陣/向量運算用 SIMD — System.Numerics 或 TensorPrimitives
  6. 常數乘法讓編譯器優化 — 明確常數、避免變數阻礙常數摺疊
  7. 多載乘法遵循數學律 — 交換律 (a*b = b*a)、結合律、(分配律)

精通乘法運算的類型語意、溢位邊界與硬體加速路徑,是高效能數值計算與領域建模的核心能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved