711 Stimmen

Was ist die maximale Rekursionstiefe und wie kann sie erhöht werden?

Ich habe diese Endrekursive Funktion hier:

def recursive_function(n, sum):
    if n < 1:
        return sum
    else:
        return recursive_function(n-1, sum+n)

c = 998
print(recursive_function(c, 0))

Es funktioniert bis n=997, dann bricht es einfach ab und gibt einen RecursionError: maximum recursion depth exceeded in comparison aus. Ist das einfach ein Stacküberlauf? Gibt es einen Weg, das zu umgehen?

4 Stimmen

21 Stimmen

Memoisierung könnte die Geschwindigkeit Ihrer Funktion steigern und ihre effektive rekursive Tiefe erhöhen, indem zuvor berechnete Werte beendet werden, anstatt die Stapelgröße zu erhöhen.

6 Stimmen

Die Rekursionsobergrenze beträgt in der Regel 1000.

12voto

Marcelo Cantos Punkte 173498

Verwenden Sie eine Sprache, die Tail-Call-Optimierung garantiert. Oder verwenden Sie Iteration. Alternativ können Sie sich mit Dekoratoren versuchen.

52 Stimmen

Das ist eher das Kind mit dem Bade ausschütten.

5 Stimmen

@Russell: Nur eine der von mir angebotenen Optionen empfiehlt dies.

0 Stimmen

"Werden Sie mit Dekorateuren niedlich" ist nicht wirklich eine Option.

12voto

Daniel Punkte 3134

Ich weiß, dass dies eine alte Frage ist, aber für diejenigen, die dies lesen, würde ich davon abraten, Rekursion für Probleme wie dieses zu verwenden - Listen sind viel schneller und vermeiden Rekursion komplett. Ich würde das so implementieren:

def fibonacci(n):
    f = [0,1,1]
    for i in xrange(3,n):
        f.append(f[i-1] + f[i-2])
    return 'Die %.0fte Fibonacci-Zahl ist: %.0f' % (n,f[-1])

(Verwenden Sie n+1 in xrange, wenn Sie Ihre Fibonacci-Folge ab 0 anstatt ab 1 zählen.)

20 Stimmen

Warum O(n) Speicherplatz nutzen, wenn man auch O(1) nutzen kann?

16 Stimmen

Nur für den Fall, dass der O(n) Speicher-Kommentar verwirrend war: Verwenden Sie keine Liste. Eine Liste behält alle Werte bei, wenn alles, was Sie brauchen, der n-te Wert ist. Ein einfacher Algorithmus wäre, die letzten beiden Fibonacci-Zahlen zu speichern und sie zu addieren, bis Sie zu der gelangen, die Sie benötigen. Es gibt auch bessere Algorithmen.

4 Stimmen

@Mathime: xrange wird in Python 3 einfach range genannt.

12voto

Tyler Punkte 191

Ich hatte ein ähnliches Problem mit dem Fehler "Maximale Rekursionstiefe überschritten". Ich entdeckte, dass der Fehler durch eine fehlerhafte Datei im Verzeichnis ausgelöst wurde, über das ich mit os.walk iteriert habe. Wenn du Schwierigkeiten hast, dieses Problem zu lösen und mit Dateipfaden arbeitest, achte darauf, es einzugrenzen, da es sich um eine fehlerhafte Datei handeln könnte.

3 Stimmen

Der OP gibt seinen Code an, und sein Experiment ist jederzeit reproduzierbar. Es beinhaltet keine beschädigten Dateien.

8 Stimmen

Du hast Recht, aber meine Antwort ist nicht auf den OP ausgerichtet, da dies vor über vier Jahren war. Meine Antwort zielt darauf ab, denen zu helfen, die durch korrupte Dateien indirekt MRD-Fehler verursacht haben - da dies einer der ersten Suchergebnisse ist. Es hat jemandem geholfen, da es positiv bewertet wurde. Vielen Dank für den negativen Bewertung.

5 Stimmen

Dies war das einzige, was ich überhaupt gefunden habe, als ich nach meinem Problem gesucht habe, das eine "maximale Rekursionstiefe" Traceback mit einer beschädigten Datei in Verbindung brachte. Vielen Dank!

9voto

rwst Punkte 2347

Natürlich können Fibonacci-Zahlen in O(n) berechnet werden, indem die Binet-Formel angewendet wird:

from math import floor, sqrt

def fib(n):                                                     
    return int(floor(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))+0.5))

Wie die Kommentarschreiber bemerken, ist es nicht O(1), sondern O(n) aufgrund von 2**n. Ein Unterschied besteht auch darin, dass man nur einen Wert erhält, während man mit Rekursion alle Werte von Fibonacci(n) bis zu diesem Wert erhält.

9 Stimmen

Es gibt keine maximale Größe eines long in Python.

14 Stimmen

Es ist erwähnenswert, dass dies bei größeren n aufgrund von Fließkommaungenauigkeiten fehlschlägt - der Unterschied zwischen (1+sqrt(5))**n und (1+sqrt(5))**(n+1) wird kleiner als 1 ulp, so dass ungenaue Ergebnisse auftreten.

3 Stimmen

Es gibt eigentlich keine großen Ganzzahlen in NumPy ...

8voto

bebidek Punkte 564

Wenn Sie nur einige Fibonacci-Zahlen erhalten möchten, können Sie die Matrixmethode verwenden.

from numpy import matrix

def fib(n):
    return (matrix('0 1; 1 1', dtype='object') ** n).item(1)

Es ist schnell, da numpy einen schnellen Exponentiierungsalgorithmus verwendet. Sie erhalten die Antwort in O(log n). Und es ist besser als die Formel von Binet, weil sie nur Ganzzahlen verwendet. Wenn Sie jedoch alle Fibonacci-Zahlen bis n erhalten möchten, ist es besser, dies durch Memorierung zu tun.

2 Stimmen

Leider können Sie numpy nicht bei den meisten Wettbewerbsprogrammierrichtern verwenden. Aber ja, Ihre Lösung ist mein Favorit. Ich habe die Matrixlösung für einige Probleme verwendet. Es ist die beste Lösung, wenn Sie eine sehr große Fibonacci-Zahl benötigen und kein Modul verwenden können. Wenn Sie ein Modul verwenden dürfen, ist die Pisano-Periode der bessere Weg, es zu tun.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X