《C 程序設計(第四版)》習題 5-10 要求計算分數序列 2/1 + 3/2 + 5/3 + 8/5 + 13/8 + 21/13 ... 前 20 項的和。這是一個分子、分母皆為斐波那契數列變體的序列。
許多初學者編寫如下代碼,但輸出結果為 21.000000,而標準答案約為 32.660261:
#include <stdio.h>
int fenzi(int n);
int fenmu(int m);
int main() {
int i;
float s = 0, tem;
for (i = 1; i <= 20; i++) {
tem = fenzi(i) / fenmu(i); // 錯誤:整數除法
s = s + tem;
}
printf("%f", s);
return 0;
}
int fenzi(int n) {
if (n == 1) return 2;
else if (n == 2) return 3;
else return (fenzi(n-2) + fenzi(n-1));
}
int fenmu(int m) {
if (m == 1) return 1;
else if (m == 2) return 2;
else return (fenmu(m-2) + fenmu(m-1));
}
原因分析: fenzi(i) 與 fenmu(i) 均返回 int,C 語言中整數相除會截斷小數部分,導致每一項的值都變成 1,累加 20 次結果為 20(加上浮點數誤差顯示 21)。
在除法運算前將任一操作數轉為 double(或 float),即可得到精確的小數結果:
tem = (double)fenzi(i) / (double)fenmu(i);
完整修正版代碼:
#include <stdio.h>
int fenzi(int n);
int fenmu(int m);
int main() {
int i;
float s = 0, tem;
for (i = 1; i <= 20; i++) {
tem = (double)fenzi(i) / (double)fenmu(i); // 關鍵修正
s = s + tem;
}
printf("%f", s); // 輸出 32.660261
return 0;
}
int fenzi(int n) {
if (n == 1) return 2;
else if (n == 2) return 3;
else return (fenzi(n-2) + fenzi(n-1));
}
int fenmu(int m) {
if (m == 1) return 1;
else if (m == 2) return 2;
else return (fenmu(m-2) + fenmu(m-1));
}
s 建議使用 double 以提高精度。printf("%.10f", s) 控制小數位數。本題核心考點是 整數除法截斷 與 浮點數類型轉換。只要在除法前加上 (double) 強轉,即可獲得正確答案。同時也提醒初學者注意遞歸的性能問題,實際工程中優先選擇迭代實現。