萊布尼茨級數:`π = 4 × (1 - 1/3 + 1/5 - 1/7 + ...)` 收斂極慢 (需 ~5000 項達 3 位精度),遞迴深度過大易堆疊溢位。
尼爾坎塔級數:`π = 3 + 4/(2×3×4) - 4/(4×5×6) + 4/(6×7×8) - ...` 收斂快得多 (約 20 項達 3 位精度),適合遞迴實作。
第 k 項 (k 從 1 起):
分母起始偶數 `d = 2k`
項值 `term = 4 / (d * (d+1) * (d+2))`
正負號 `sign = (k % 2 == 1) ? +1 : -1` (第一項正)
累加:`pi = 3 + Σ sign * term`
#include
#include
/**
* 尼爾坎塔級數遞迴計算 π
* @param k 當前項索引 (從 1 開始)
* @param pi_acc 累積 π 值 (初始 3.0)
* @param target 目標精度 (如 0.0005 保證小數點後 3 位正確)
* @return 計算完成的 π 值
*/
double piNilakanthaRecursive(int k, double pi_acc, double target) {
// 分母起始偶數
int d = 2 * k;
// 當前項值
double term = 4.0 / (d * (d + 1) * (d + 2));
// 正負號:奇數項正、偶數項負
double sign = (k % 2 == 1) ? 1.0 : -1.0;
double current_term = sign * term;
// 新累積值
double new_pi = pi_acc + current_term;
// 終止條件:當前項絕對值小於目標精度 (級數交錯收斂,誤差 < 首個被忽略項)
if (fabs(current_term) < target) {
return new_pi;
}
// 尾遞迴:下一項
return piNilakanthaRecursive(k + 1, new_pi, target);
}
int main() {
// 目標精度 0.0005 確保四捨五入到小數點後 3 位正確 (3.141)
double pi = piNilakanthaRecursive(1, 3.0, 0.0005);
printf("π ≈ %.10f\n", pi); // 3.1415926536...
printf("π ≈ %.3f\n", pi); // 3.142 (四捨五入)
// 實際 π = 3.141592653589793...
return 0;
}
| k | d | term | sign | current_term | pi_acc |
|---|---|---|---|---|---|
| 0 | - | - | - | - | 3.0000000000 |
| 1 | 2 | 4/(2·3·4)=0.1666667 | + | +0.1666667 | 3.1666666667 |
| 2 | 4 | 4/(4·5·6)=0.0333333 | - | -0.0333333 | 3.1333333333 |
| 3 | 6 | 4/(6·7·8)=0.0119048 | + | +0.0119048 | 3.1452380952 |
| 4 | 8 | 4/(8·9·10)=0.0055556 | - | -0.0055556 | 3.1396825397 |
| 5 | 10 | 4/(10·11·12)=0.0030303 | + | +0.0030303 | 3.1427128427 |
| ... | ... | ... | ... | ... | ... |
| ~20 | ~40 | <0.0005 | - | <0.0005 | 3.14159... |
π ≈ 3.1415926536
π ≈ 3.142
四捨五入到小數點後 3 位為 **3.142** (實際 π=3.14159...,第三位為 1,第四位 5 進位)。
`π/4 = 4*arctan(1/5) - arctan(1/239)`
`arctan(x) = x - x³/3 + x⁵/5 - ...` (x<1 時收斂極快)
遞迴實作 `arctan` 尾遞迴即可,約 5-10 項達雙精度極限。
使用 **尼爾坎塔級數** 遞迴計算 π,約 20 層遞迴即達小數點後 3 位精度,避免萊布尼茨級數堆疊溢位風險。關鍵在於**交錯級數誤差界估計** (`|error| < |first_omitted_term|`) 作為遞迴終止條件。**教學展示遞迴替代迴圈可行,實務請用 `M_PI` 常數或標準庫函數。**