Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Revision; result überschreiben (https://www.delphipraxis.net/177474-revision%3B-result-ueberschreiben.html)

Mokus 8. Nov 2013 09:23

Delphi-Version: XE2

Revision; result überschreiben
 
Bei der Folgende Function wird mein result immer überschrieben;

Delphi-Quellcode:
function TForm1.Fakulitaet(
  n       : integer;
  max     : integer;
  iErgebnis: integer): integer;
var
  I: integer;
begin
  if n <= max then
  begin
    iErgebnis := iErgebnis * n;
    n        := n + 1;
    result   := iErgebnis;
    self.Fakulitaet(n, max, iErgebnis);
  end;

end;
Er rechnet richtig, bei 5 120 etc.

Das result ist aber ständig eins ....

Wie kann man bei einer rekusiven Function das result nehmen, welches am letzten herausgefunden war.

baumina 8. Nov 2013 09:32

AW: Revision; result überschreiben
 
Du rufst die Funktion procedural auf:

Delphi-Quellcode:
self.Fakulitaet(n, max, iErgebnis);
statt

Delphi-Quellcode:
xxx := Fakulitaet(n, max, iErgebnis);

Medium 8. Nov 2013 09:33

AW: Revision; result überschreiben
 
Delphi-Quellcode:
function TForm1.Fakultaet(
  n       : integer;
  max     : integer;
  iErgebnis: integer): integer;
begin
  if n <= max then
    result := Fakulitaet(n+1, max, iErgebnis*n);
end;
Die Fakulität heisst übrigens nur Fakultät, und die Revision im Titel soll vermutlich eine Rekursion sein :)

Mokus 8. Nov 2013 09:44

AW: Revision; result überschreiben
 
Delphi-Quellcode:
function TForm1.Fakulitaet(
  n       : integer;
  max     : integer;
  iErgebnis: integer): integer;
begin
  if n <= max then
  begin
    iErgebnis := iErgebnis * n;
    n        := n + 1;
    result   := self.Fakulitaet(n, max, iErgebnis); // falsche zuweisung fehlte,
  end
  else
  begin
    result := iErgebnis; // damit auch richtiges ergebnis kommt
  end;

kleines else und ne result zuweisung haben gefehlt;
dank euch :)

Uwe Raabe 8. Nov 2013 10:00

AW: Revision; result überschreiben
 
Entschuldige bitte die Kritik, aber das ist m.E. viel zu kompliziert implementiert, was auch zu einer schlechten Lesbarkeit und Fehleranfälligkeit führt.

Du führst unnötigerweise den Endwert und das Zwischenergebnis bei jedem Funktionsaufruf mit. Dabei wird unnütz viel Stack verbraucht. Bei der Fakultät wird zwar wohl erst der Integerüberlauf vor einem Stacküberlauf eintreten, aber man sollte doch seine Resourcen gerade bei Rekursionen nicht unnötig verschwenden.

Günstiger ist es hier, das Pferd von hinten aufzuzäumen:

Delphi-Quellcode:
function Fakultaet(n: Integer): Integer;
begin
  if n = 1 then
    result := 1
  else
    result := n*Fakultaet(n-1);
end;

noisy_master 8. Nov 2013 12:08

AW: Revision; result überschreiben
 
Moin,

Zitat:

Zitat von Uwe Raabe (Beitrag 1235065)
...wird unnütz viel Stack verbraucht..... Stacküberlauf eintreten,

Günstiger ist es hier, das Pferd von hinten aufzuzäumen:

Delphi-Quellcode:
function Fakultaet(n: Integer): Integer;
begin
  if n = 1 then
    result := 1
  else
    result := n*Fakultaet(n-1);
end;

Dann sparen wir uns doch am besten die Rekursion komplett(spart noch mehr Stack) und frühstücken das ganze mit einer simplem loop ab....

Delphi-Quellcode:
function Fakultaet(n: Integer): Integer;
var i:integer;
begin
  result := 1;
  // just start at 2, because 0! and 1! is 1
  for i:= 2 to n do
    result := result * i;
end;

P.S.: funktioniert natürlich so nur für die Fakultät von positiven Zahlen ;-)

Der schöne Günther 8. Nov 2013 12:28

AW: Revision; result überschreiben
 
Da der rekursive Funktionsaufruf die letzte Anweisung der Methode war, würde ich so etwas eigentlich schon dem Compiler überlassen, dass dahingehend zu optimieren ("Tail Recursion").

Der Delphi Win32-Compiler optimiert das (glaube ich) zwar nicht dahingehend, aber das geht alles irgendwie auch schon weit über die ursprüngliche Frage hinaus ;-)

Uwe Raabe 8. Nov 2013 12:40

AW: Revision; result überschreiben
 
Zitat:

Zitat von noisy_master (Beitrag 1235076)
Dann sparen wir uns doch am besten die Rekursion komplett(spart noch mehr Stack) und frühstücken das ganze mit einer simplem loop ab....

Ich weiß nicht, ob das hier der Fall ist, aber die Berechnung der Fakultät wird im Informatik-Unterricht gern als Beispiel für Rekursion genommen. Dazu möchte ich hier gern noch eine Anekdote aus dem Informatik-Unterricht (Pascal) meiner Tochter loswerden:

Zitat:

Lehrer: Wir nennen die Funktion mal FAK.
(Tosendes Gelächter im Klassenraum)
Lehrer: Na gut. Dann eben FAKU.

himitsu 8. Nov 2013 13:15

AW: Revision; result überschreiben
 
Zitat:

Zitat von Mokus (Beitrag 1235059)
Delphi-Quellcode:
function TForm1.Fakulitaet(
  n       : integer;
  max     : integer;
  iErgebnis: integer): integer;
var
  I: integer;
begin
  if n <= max then
  begin
    iErgebnis := iErgebnis * n;
    n        := n + 1;
    result   := iErgebnis;
    self.Fakulitaet(n, max, iErgebnis);
  end;

end;

Dein Compiler gibt da nicht zufällig eine Warnung aus, bezüglich "Result sei nicht initialisiert" :?:
(Nja, und "i wurde deklariert, aber nicht verwendet".)

Und daß du das Ergebnis von dem rekursiven Fakulitaet-Aufruf nicht auswertest, hatte hier schon jemand erwähnt.


PS: Seit 2009 kannst du auch beruhigt "Fakulität" schreiben.

Uwe Raabe 8. Nov 2013 13:35

AW: Revision; result überschreiben
 
Zitat:

Zitat von himitsu (Beitrag 1235089)
PS: Seit 2009 kannst du auch beruhigt "Fakulität" schreiben.

Wäre aber auch nicht richtig...:)


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz