Даже решение проблемы использования постинкремента, чтобы рекурсия продолжалась вечно, это не очень подходит для рекурсивного решения - см. здесь , почему, но все сводится к тому, насколько быстро вы можете уменьшить пространство поиска.
Хотя ваше деление huge_number
довольно быстро сокращает его, подавляющее большинство рекурсивных вызовов выполняется простым увеличением n
. Это означает, что вы собираетесь использовать лот стекового пространства.
Вам было бы лучше либо:
- использование итеративного решения, при котором вы не выбросите стек (если вы просто хотите решить проблему) (a) ; или
- поиск более подходящей задачи для рекурсии, если вы просто пытаетесь изучить рекурсию.
(a) Примером такого зверя, смоделированного на вашем рекурсивном решении, является:
#include <stdio.h>
long long prime_factor_i (int n, long long huge_number) {
while (n < huge_number) {
if (huge_number % n == 0) {
huge_number /= n;
continue;
}
n++;
}
return huge_number;
}
int main (void) {
int n = 2;
long long huge_number = 60085147514LL;
long long largest_prime = 0;
largest_prime = prime_factor_i (n, huge_number);
printf ("%lld\n", largest_prime);
return 0;
}
Как видно из результатов этого итеративного решения, наибольшим фактором является 10976461
. Это означает, что финальная партия рекурсий в вашем рекурсивном решении потребует глубины стека в десять миллионов стековых фреймов, с чем не легко справится большинство сред.
Если вы действительно должны использовать рекурсивное решение, вы можете уменьшить пространство стека до квадратного корня из этого, используя тот факт, что у вас нет , чтобы проверить все вплоть до числа, но только до его квадратного корня.
Кроме того, кроме 2
, все остальные простые числа нечетные, поэтому вы можете дополнительно сократить пространство поиска вдвое, проверив только два плюс нечетные числа.
Рекурсивное решение, учитывающее эти две вещи:
long long prime_factor_r (int n, long long huge_number) {
// Debug code for level checking.
// static int i = 0;
// printf ("recursion level = %d\n", ++i);
// Only check up to square root.
if (n * n >= huge_number)
return huge_number;
// If it's a factor, reduce the number and try again.
if (huge_number % n == 0)
return prime_factor_r (n, huge_number / n);
// Select next "candidate" prime to check against, 2 -> 3,
// 2n+1 -> 2n+3 for all n >= 1.
if (n == 2)
return prime_factor_r (3, huge_number);
return prime_factor_r (n + 2, huge_number);
}
Вы можете видеть, что я также удалил (неудобно, на мой взгляд) конструкцию:
if something then
return something
else
return something else
Я предпочитаю менее массивный код с отступом, который исходит от:
if something then
return something
return something else
Но это всего лишь личные предпочтения. В любом случае, это снижает уровень рекурсии до 1662 (раскомментируйте отладочный код для проверки), а не до десяти миллионов, что является значительным сокращением, но все же не идеальным. Это нормально работает в моей среде.