// 遞歸求素數
// by winxos 2011-08-29
#include <stdio.h>
// #include <math.h>
int isdiv(int a, int b)
{
// if (b == (int)sqrt(a) + 1) return 0; // 快但不優雅
if (b == a - 1) return 0;
if (a % b == 0) return 1;
return isdiv(a, b + 1); // 缺少 return,原代碼有 Bug
}
int isprime(int n)
{
if (n < 2) return 0;
if (n == 2) return 1;
return !isdiv(n, 2);
}
int main()
{
for (int i = 1; i < 10000; ++i) {
if (isprime(i))
printf("%d ", i);
}
return 0;
}
isdiv 從 2 遞歸到 n-1,對 n=10000 深度近萬,極易棧溢出。isdiv(a, b+1); 未 return,導致未定義行為(現已修正)。b == (int)sqrt(a)+1 可將遞歸深度降至 √n,但作者稱「不優雅」而放棄。int isdiv_opt(int a, int b)
{
if (b * b > a) return 0; // √n 剪枝
if (a % b == 0) return 1;
return isdiv_opt(a, b + 1); // 尾遞歸,編譯器可優化為迭代
}
int isprime_opt(int n)
{
if (n < 2) return 0;
if (n == 2) return 1;
if (n % 2 == 0) return 0; // 排除偶數
return !isdiv_opt(n, 3); // 從 3 開始,步長 2
}
配合 -O2 編譯,尾遞歸會被優化為循環,棧深度恆為 O(1)。
原代碼展示了遞歸思維,但存在棧溢出、缺返回值、複雜度高等多重問題。工程實踐中,正確性 > 優雅 > 性能,請優先選擇成熟算法與庫函數。