Rekursive Funktion klappt nicht!
-
Hi,
ich habe ein kleines C++ programm geschrieben welches als Ergebnis
die Fakultät berechnen soll, es funktioniert nur nicht wie erwartet.
Als Ergebnis erhalte ich in jedem Fall Null.#include<iostream.h> using namespace std ; long fakultaet (unsigned long n) { if (n==0) return 1 ; else { cout << n; return n*fakultaet(--n); } } int main () { unsigned long n=0; cout << "Berechnung der Fakultät \n\n" ; cout << "Bitte eine Zahl eingeben : " ; cin >> n ; cout << "Ergebnis : " << fakultaet(n); cin >> n; return 0; }Ich bin jetzt dahinter gekommen das es an dem Dekrementoperator liegen muss,
denn wenn ich es abändere zureturn n*fakultaet(n-1);funktioniert es einwandfrei.
Ich weiß das --n den Wert von n um 1 erniedrigt soweit ist es äquivalent mit der zweiten Möglichkeit. Der Unterschied besteht jetzt jedoch darin das dieser
Wert in der lokalen Variable n gespeichert wird. Dieser gespeicherte Wert der
jetzt nach Dekrementierung in n enthalten ist, wird doch als Parameter beim
nächsten Aufruf der Funktion fakulteat betrachtet.Wo ist mein Denkfehler?
-
1. Der Titel stimmt ja mal überhaupt nicht mit dem Problem überein

2. Es ist nicht definiert, wann der Wert von n evaluiert wird:n * fakultaet(--n); // 1 2Es gibt keine Definition darüber, wann der Wert von 1 oder 2 evaluiert wird. In deinem Fall wurde wohl der Wert von 1 erst nach dem Wert von 2 evaluiert, wodurch 0 herauskam.
Grüssli
-
Meinst du das es mit der Evaluierung an der Assoziativtät des Operanden
liegen kann, ich hab die Faktoren einfach mal getauscht und der Fehler bleibt
trotzdem. Heißt für mich das dies nichts mit dem Problem gemein hat.Es muss folglich an der Definition von Prä- und Postfixschreibweise liegen die
in diesem Falle nicht eindeutig geklärt ist.
Nur bleibt für mich unverständlich warum es bei den vielen Verbesserungen und Versionen von C(ANSI C,C99) und C++ bei soetwas primitivem keine genaue Definition gibt.Werde ich mir irgendwo aufschreiben damit ich mir es merke.
-
Nein es geht darum, wann der Faktor n am Anfang ausgewertet wird. Das kann passieren vor oder nach dem Dekrement. Das ist nicht definiert und dem Kompiler überlassen.
Ein Faktor weiter vorne wird nicht immer auch vor den anderen evaluiert. Wenn du folgende Rechnung hast:
x = a * b * c * d;
Dann kann womöglich zuerst d, dann b, dann c und dann erst a evaluiert werden. Die Reihenfolge ist völlig dem Kompiler überlassen.Genau das passiert bei dir. Weil es nicht definiert ist, macht dein Kompiler halt das folgende. Er wertet zuerst --n (wenn n 1, dann ist n nun 0) aus, ruft dann womöglich die Funktion auf und führt dann erst die Multiplikation durch, wo er nun n (ist nun 0) aus dem Speicher liest.
Die Reihenfolge der Auswertung der Operanden ist nicht definiert.
Grüssli
-
dummyjooooooo schrieb:
Nur bleibt für mich unverständlich warum es bei den vielen Verbesserungen und Versionen von C(ANSI C,C99) und C++ bei soetwas primitivem keine genaue Definition gibt.
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
-
Dravere schrieb:
Die Reihenfolge der Auswertung der Operanden ist nicht definiert.
Einen kleinen Nachtrag meinerseits sei erlaubt. Das ist leider immer noch das Fiese an C/C++. Trotz >25 Jahren Erfahrung habe ich das Problem auch nicht sofort gesehen.
Merke, wenn Du einen Post- oder Preinkrement- bzw. -dekrementoperator in einem Ausdruck verwendest, sollte dessen Operand kein zweites mal im Ausdruck verwendet werden.
mfg Martin