計算階乘純加級數:f = 1! + 2! + 3! + ... + n!。與交替級數不同,此處無符號翻轉,單調遞增,溢出來得更快,更考驗類型選擇與邊界意識。
#include <stdio.h>
void f(int m);
int main() {
int n;
printf("請輸入一個數(不能太大): ");
scanf("%d", &n);
f(n);
return 0;
}
void f(int m) {
int i, j;
int s = 1;
int sum = 0;
for (i = 1; i <= m; i++) {
s = 1;
for (j = 1; j <= i; j++) {
s *= j;
}
sum += s;
s = 1;
}
printf("%d\n", sum);
}
交替級數中正負抵消延緩溢出,純加級數單調增長:
| n | 1!+...+n! (int) | 備註 |
|---|---|---|
| 7 | 5913 | 安全 |
| 8 | 46233 | 安全 |
| 9 | 409113 | 安全 |
| 10 | 4037913 | 安全 |
| 11 | 43954713 | 安全 |
| 12 | 522956313 | 安全 |
| 13 | 溢出 | 13! = 6227020800 > INT_MAX |
void f_ll(int m) {
long long fact = 1, sum = 0;
for (int i = 1; i <= m; i++) {
fact *= i;
sum += fact;
}
printf("long long 結果: %lld\n", sum); // 支持到 n=20
}
原代碼 O(n²) 重複計算階乘,遞推版 O(n):
// 原版:每次 i 重新算 i!,總操作 ~ n²/2 次乘法
// 優化版:fact 遞推,總操作 n 次乘法
#include <stdio.h>
#include <limits.h>
void factorial_sum(int n) {
if (n < 1) { printf("n 必須 ≥ 1\n"); return; }
// 嘗試用 unsigned long long (0 ~ 1.84e19),比 signed 多一倍範圍
unsigned long long fact = 1, sum = 0;
int overflow = 0;
for (int i = 1; i <= n; i++) {
// 溢出檢測:fact > ULLONG_MAX / i
if (fact > ULLONG_MAX / i) {
printf("在第 %d 階乘處溢出 (unsigned long long)\n", i);
overflow = 1;
break;
}
fact *= i;
if (sum > ULLONG_MAX - fact) {
printf("在第 %d 項累加處溢出\n", i);
overflow = 1;
break;
}
sum += fact;
}
if (!overflow) {
printf("1!+2!+...+%d! = %llu\n", n, sum);
} else {
printf("建議使用大整數庫 (如 GMP) 計算更大 n\n");
}
}
int main() {
int n;
printf("請輸入 n (1~20 建議): ");
if (scanf("%d", &n) == 1) factorial_sum(n);
return 0;
}
此級數無簡單閉式,但與次階乘 !n = n! Σ(-1)^k/k!、不完全伽馬函數 有關。工程應用見於排列組合計數、期望值計算等。
階乘純加級數是「遞推優化、類型邊界、溢出防禦」的絕佳練習場。核心收穫:
int 12!、long long 20!、double 170!;