計算前 100 項交替調和級數部分和,展示數學庫函數法與旗標變數法的差異,並分析浮點數精度特性。
#include <stdio.h>
#include <math.h>
int main() {
double sum = 0.0;
for (int n = 1; n <= 100; n++) {
// (-1)^(n+1):n=1 為 +1, n=2 為 -1, n=3 為 +1...
double sign = pow(-1.0, n + 1);
sum += sign / n;
}
printf("方法一結果:%.12f\n", sum);
printf("ln(2) 參考值:%.12f\n", log(2.0));
printf("絕對誤差:%.2e\n", fabs(sum - log(2.0)));
return 0;
}
#include <stdio.h>
int main() {
double sum = 0.0;
int sign = 1; // 從正號開始
for (int n = 1; n <= 100; n++) {
sum += sign * (1.0 / n);
sign = -sign; // 每次翻轉
}
printf("方法二結果:%.12f\n", sum);
printf("ln(2) 參考值:%.12f\n", 0.693147180560);
return 0;
}
| 維度 | pow() 法 | 旗標法 |
|---|---|---|
| CPU 週期 | ~100-200 cycles/次 | ~3-5 cycles/次 |
| 函數呼叫 | 需連結 math library (-lm) | 純整數/浮點運算 |
| 數值穩定性 | 良好 | 良好 |
| 程式碼可讀性 | 數學定義直觀 | 演算法邏輯直觀 |
1/n 會整數除法截斷為 0-O2 下旗標法會被優化為無分支碼// 僅需 50 次迴圈達到相同精度
double sum = 0.0;
for (int k = 1; k <= 50; k++) {
sum += 1.0 / (2 * k * (2 * k - 1));
}
printf("加速版 (50項):%.12f\n", sum);
-lm 連結數學庫(pow 版本)1/n 導致結果為 0