<asp:TextBox ID="txtInput" runat="server" />
<asp:Button ID="btnCalc" runat="server" Text="計算階乘" OnClick="btnCalc_Click" />
<asp:TextBox ID="txtResult" runat="server" ReadOnly="true" />
protected void btnCalc_Click(object sender, EventArgs e) {
if (int.TryParse(txtInput.Text.Trim(), out int n) && n >= 0) {
try {
txtResult.Text = Factorial(n).ToString();
} catch (StackOverflowException) {
txtResult.Text = "輸入過大,棧溢出";
} catch (OverflowException) {
txtResult.Text = "結果超出 Int32 範圍";
}
} else {
txtResult.Text = "請輸入非負整數";
}
}
private static int Factorial(int n) {
if (n == 0) return 1; // 遞歸出口:0! = 1
return n * Factorial(n - 1); // 遞歸調用
}
| 特點 | 說明 | 階乘案例體現 |
|---|---|---|
| 自我調用 | 函數內部直接/間接調用自身 | Factorial(n-1) |
| 必須有出口 | 無出口導致無限遞歸 → 棧溢出 | if (n==0) return 1; |
| 代碼簡潔 | 邏輯直觀,符合數學定義 | 僅 2 行核心代碼 |
| 效率較低 | 函數調用開銷、棧幀分配、重複計算 | n=20 即超出 Int32,n>1000 棧溢出 |
// 迭代版(推薦生產環境)
private static long FactorialIterative(int n) {
long result = 1;
for (int i = 2; i <= n; i++) result *= i;
return result;
}
// 尾遞歸優化(C# 編譯器不保證優化,僅作演示)
private static long FactorialTailRec(int n, long acc = 1) {
return n == 0 ? acc : FactorialTailRec(n - 1, acc * n);
}
| 指標 | 遞歸 | 迭代 | 尾遞歸 |
|---|---|---|---|
| 時間複雜度 | O(n) | O(n) | O(n) |
| 空間複雜度 | O(n) 棧深度 | O(1) | O(1)* 若編譯器優化 |
| 最大安全 n (Int64) | 20 | 20 | 20 |
| 棧溢出風險 | 高 (n>1000) | 無 | 低(理論) |
System.Numerics.BigInteger
using System.Numerics;
private static BigInteger FactorialBig(int n) {
BigInteger result = 1;
for (int i = 2; i <= n; i++) result *= i;
return result;
}
// FactorialBig(100) 即可計算 100! (158 位數字)
階乘屬線性遞歸,實際開發中遞歸更適合:
「遞歸是思維工具,迭代是工程選擇。」—— 理解遞歸本質,在正確場景選擇正確實現。