Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Funktion deklarieren oder nicht? (https://www.delphipraxis.net/179394-funktion-deklarieren-oder-nicht.html)

Ergosquare 4. Mär 2014 14:33

Funktion deklarieren oder nicht?
 
Hallo.

Es geht um eine Variable, die für eine Grafik wichtig ist und durch eine Funktion deklariert wird.
Es scheint, als ob die Funktion nicht ausgeführt werden würde.
In der Grafik erscheint dann nur eine vollfarbige Fläche, obwohl man mindestens eine Struktur erkennen müsste

Code:
function zaehler(za:integer; x,y,x2,a,b:real):integer;
begin
    x2:=x*x-y*y+a;                                
    y:=2*x*y+b;
    x:=x2;
    If (za<100) and (sqrt(x*x+y*y)<2)              
    then za:=zaehler(za+1,x,y,x2,a,b)              
    else za:=1;
end;

   .
   .
   .

    za:=0;                         //Initialisierung
    zaehler(za,x,y,x2,a,b);        //Aufruf
    if za>=100 then paintbox1.canvas.Pixels[s+50,z+50]:=clBlack;
    case za of
        0..9:paintbox1.canvas.Pixels[s+50,z+50]:=clRed;                  
        10..19:paintbox1.canvas.Pixels[s+50,z+50]:=clGreen;

   .
   .
   .

Furtbichler 4. Mär 2014 14:35

AW: Funktion deklarieren oder nicht?
 
Wenn Du einen Parameter innerhalb der Funktion/Prozedur/Methode veränderst, musst Du ihn mit 'var' deklarieren, also
Delphi-Quellcode:
function zaehler(var za:integer; var x,y,x2,a,b:real):integer;
begin
    x2:=x*x-y*y+a;                                
    y:=2*x*y+b;
    x:=x2;
    If (za<100) and (sqrt(x*x+y*y)<2)            
    then za:=zaehler(za+1,x,y,x2,a,b)            
    else za:=1;
end;

DeddyH 4. Mär 2014 14:36

AW: Funktion deklarieren oder nicht?
 
Delphi-Quellcode:
function zaehler(var za:integer; var x,y,x2,a,b:real):integer;
So besser?

[edit] Einen Tick zu langsam. Möglichweise kann man die Fließkommaparameter aber auch by Value übergeben (also ohne das "var"), so genau hab ich das jetzt nicht durchdrungen. [/edit]

Zoot 4. Mär 2014 14:41

AW: Funktion deklarieren oder nicht?
 
Man könnte za auch im Result der Function übergeben.
Ansonsten wäre eine Procedure sinnvoller.

Nachtrag:
Ohne Result := za geht der rekursive Aufruf sowieso nicht.

DeddyH 4. Mär 2014 14:45

AW: Funktion deklarieren oder nicht?
 
Stimmt, ist mir gar nicht aufgefallen :oops:

himitsu 4. Mär 2014 14:54

AW: Funktion deklarieren oder nicht?
 
Eine Rekursion mit
Delphi-Quellcode:
procedure zaehler(var za:integer; x,y,x2,a,b:real);
ginge schon, aber dann müsste man die Logik anpassen, damit Diese dann "eigentlich" als Iteration arbeitet, womit man den rekursiven Aufruf dann aber auch gleich entsorgen könnte.

Ergosquare 4. Mär 2014 14:59

AW: Funktion deklarieren oder nicht?
 
Hallo nochmal.

Mit der Variante bekomme ich die Fehlermeldungen:

[Fehler] Unit1.pas(36): ';', ')' oder '=' erwartet, aber 'VAR' gefunden
[Fehler] Unit1.pas(42): Die Typen der tatsächlichen und formalen Var-Parameter müssen übereinstimmen

Code:
function zaehler(var za:integer var x,y,x2,a,b:real):integer; //36
begin
    x2:=x*x-y*y+a;                                
    y:=2*x*y+b;
    x:=x2;
    If (za<100) and (sqrt(x*x+y*y)<2)              
    then za:=zaehler(za+1,x,y,x2,a,b)              //42
    else za:=1;
end;
Was ist mit
result:=za;
gemeint?
Die Variablen ändern sich doch durch die Funktion, oder nicht?

Der rek. Aufruf ist schon Absicht.

MfG Ergosquare

p80286 4. Mär 2014 15:07

AW: Funktion deklarieren oder nicht?
 
Delphi-Quellcode:
function zaehler(var za:integer; var x,y,x2,a,b:real):integer; //36
Gruß
K-H

DeddyH 4. Mär 2014 15:08

AW: Funktion deklarieren oder nicht?
 
Da fehlt ein Semikolon im Funktionskopf vor dem zweien "var". Und eine Funktion hat einen Rückgabewert, der wird in Deinem Code aber nirgends gesetzt, der Compiler müsste auch eine diesbezügliche Warnung ausgeben.

p80286 4. Mär 2014 15:15

AW: Funktion deklarieren oder nicht?
 
Zitat:

Zitat von DeddyH (Beitrag 1250580)
Und eine Funktion hat einen Rückgabewert, der wird in Deinem Code aber nirgends gesetzt

Wenn man die Tomaten zur Seite schiebt, sieht man auch das.

Gruß
K-H

DeddyH 4. Mär 2014 15:17

AW: Funktion deklarieren oder nicht?
 
Und wo soll das sein?

Ergosquare 4. Mär 2014 15:20

AW: Funktion deklarieren oder nicht?
 
Sorry, mein Fehler, das mit dem Semikolon hätte ich sehen können.

Das zweite Problem besteht weiterhin.

Eine Warnung bekomme ich nicht.

MfG Ergosquare

DeddyH 4. Mär 2014 15:26

AW: Funktion deklarieren oder nicht?
 
2 Möglichkeiten:
Delphi-Quellcode:
function SomeFunction: integer;
begin
  Result := 42; (* Result *)
end;
oder auch
Delphi-Quellcode:
function SomeFunction: integer;
begin
  SomeFunction := 42; (* Funktionsname *)
end;
Auch nach 20-maligem Drübergucken habe ich in Deinem Code keine der beiden Möglichkeiten entdecken können. Du musst also vor dem rekursiven Aufruf der Funktion einen Wert zuweisen, sonst steht da irgendetwas drin, aber nichts Definiertes. Steppe doch einmal durch und schau Dir den Wert von za nach dem Aufruf an. Nach meinem Dafürhalten müsste da ziemlicher Nonsens drinstehen.

p80286 4. Mär 2014 15:27

AW: Funktion deklarieren oder nicht?
 
Zitat:

Zitat von DeddyH (Beitrag 1250583)
Und wo soll das sein?

Na nirgens! (ich hätte geschworen das da was war)

Gruß
K-H

DeddyH 4. Mär 2014 15:29

AW: Funktion deklarieren oder nicht?
 
Achso, Missverständnis meinerseits, ich dachte, Du hättest meine Tomaten gemeint :lol:

Ergosquare 4. Mär 2014 16:53

AW: Funktion deklarieren oder nicht?
 
So, die Funktion hat jetzt eine Rückgabewert.

za scheint trotzdem durch die Funktion nicht verändert zu werden.

MfG Ergosquare

Blup 4. Mär 2014 16:56

AW: Funktion deklarieren oder nicht?
 
Um mal zusammenzufassen:
- Rekursion ist in der Regel langsamer als Iteration
- Parameter, lokale Variablen und Rückgabewerte nicht durcheinander werfen

So stelle ich mir das vor:
Delphi-Quellcode:
function zaehler(x, y, a, b: Real): Integer;
var
  x2: Real;
begin
  Result := 0;
  while (Result <= 100) and (sqrt((x * x) + (y * y)) < 2) do
  begin
    x2 := (x * x) - (y * y) + a;                              
    y := (2 * x * y)      + b;
    x := x2;
    Inc(Result);
  end;
end;

var
  c: TColor;

  za := zaehler(x, y, a, b);
  case za of
     0..9: c := clRed;                
   10..19: c := clGreen;
{...}
  else    c := clBlack;
  end;
  paintbox1.canvas.Pixels[s + 50, z + 50] := c;
Pixels ist so ziemlich die langsamste Möglichkeit eine Grafik auszugeben.
Besser du verwendest eine Bitmap und greifst mit Scanline darauf zu.
Die Bitmap dann komplett oder nach jeder Zeile zeichnen.
Alternativ gleich mit einer TImage-Komponente arbeiten (Image1.Picture.Bitmap).

Ergosquare 4. Mär 2014 17:12

AW: Funktion deklarieren oder nicht?
 
Ich hatte noch einen entscheidenden Fehler:

Code:
    If (za<100) and (sqrt(x*x+y*y)<2)              
    then za:=zaehler(za+1,x,y,x2,a,b)+1 //+1 hat gefehlt            
    else za:=1;
Sonst wird za nach der Funktion nicht verändert.
Dennoch bleibt es leider bei der Einfarbigkeit.

PS: Ich würde trotzdem gerne bei Rekursion bleiben.

MfG Ergosquare

Furtbichler 4. Mär 2014 21:10

AW: Funktion deklarieren oder nicht?
 
Zitat:

Zitat von Blup (Beitrag 1250601)
Um mal zusammenzufassen:
- Rekursion ist in der Regel langsamer als Iteration

Um mal aufzuklären:
- Nein. Hm. Also eigentlich irgendwie doch aber nicht so einfach. ;-)
Eine sehr schöne Erklärung ist hier zu finden. Unabhängig davon kommt es auf die Implementierung an. So gibt es eben rekursive Lösungen, deren iteratives Äquivalent sehr umständlich umzusetzen und daher auch langsamer sind. Die hochoptimierten Compiler (ja, auch Delphi gehört dazu) widerum können (rekursive) Aufrufe durchaus über Register abbilden und so zu u.U. wirklich schnellerem Code führen.

sx2008 4. Mär 2014 21:14

AW: Funktion deklarieren oder nicht?
 
Den Ausdruck
Delphi-Quellcode:
(sqrt((x * x) + (y * y)) < 2)
kann man übrigens zu
Delphi-Quellcode:
((x * x) + (y * y) < 4)
vereinfachen.
Man kommt darauf wenn man den Ausdruck auf beiden Seiten des Kleinerzeichens quadriert.
Die Quadratwurzel
Delphi-Quellcode:
sqrt()
wird dann aufgehoben und das spart recht viel Zeit.

Medium 5. Mär 2014 01:04

AW: Funktion deklarieren oder nicht?
 
@Rekursion: In diesem Fall hier (Mandelbrot Fraktal) ist Geschwindigkeit nicht ganz unwichtig, da der gesamte Prozess sonst echt lahm werden kann. Und die Iteration eines Punktes geht - wie der Name der Operation schon so freundlich suggeriert - völlig klaglos und performat iterativ. Es drängt sich in meinem Hirn sogar geradezu als der "natürliche" Weg auf. (Und ja, TCanvas.Pixels[] bremst hier mindestens genau so heftig, wenn nicht sogar noch signifikanter.) (Davon ab ist 100 als Grenz-Iterationstiefe schon ziemlich fein. Bei den meisten Zooms, die das Fraktal als ganzes noch zeigen, sind Tiefen um 30-50 bei voller HD Auflösung noch sehr gut. Je näher man ran geht, desto feiner muss man allerdings werden um alle theoretisch noch sichtbaren Details zu bekommen. Ich würde die Iterationstiefe daher entweder frei wählbar (favorit), oder vom Zoom abhängig machen.)

Furtbichler 5. Mär 2014 06:49

AW: Funktion deklarieren oder nicht?
 
Um es kurz zu machen: Bloß weil etwas rekursiv definiert ist, muss es ja nicht rekursiv umgesetzt werden.

Blup 5. Mär 2014 12:51

AW: Funktion deklarieren oder nicht?
 
Hier wegen der Vollständigkeit eine funktionierende rekursive Variante:
Delphi-Quellcode:
procedure zaehler(var za: Integer; x, y, a, b: Real);
var
  x2, y2: Real;
begin
  if za = 100 then
    Exit;

  x2 := x * x;
  y2 := y * y;
  if (x2 + y2) >= 4 then
    Exit;

  Inc(za);
  zaehler(za, x2 - y2 + a, (2 * x * y) + b, a, b);  
end;

Medium 5. Mär 2014 13:58

AW: Funktion deklarieren oder nicht?
 
Und hier eine iterative:
Delphi-Quellcode:
function zaehler(x, y, a, b: Real): Integer;
begin
  result := 0;
  repeat
    x := x*x + y*y + a;
    y := 2*x*y + b;
    Inc(result);
  until (result>100) or ((x*x+y*y)>=4);
end;

Blup 6. Mär 2014 08:46

AW: Funktion deklarieren oder nicht?
 
@Medium

Deine Berechnung ist aber Falsch:
- für die Berechnung des neuen x' muss (y * y) subtrahiert werden
- für die Berechnung des neuen y' muss das alte x in der Berechnung benutzt werden
Delphi-Quellcode:
function zaehler(x, y, a, b: Real): Integer;
var
  x2, y2: Real;
begin
  Result := 0;
  repeat
    x2 := x * x;
    y2 := y * y;
    if (x2 + y2) >= 4 then
      Break;
    y := (2 * x * y) + b;
    x := x2 - y2 + a;
    Inc(Result);
  until (result > 100);
end;

Medium 6. Mär 2014 12:29

AW: Funktion deklarieren oder nicht?
 
Ups, stimmt. Ich hatte nur den vorhandenen Code im Editor zusamengeschnippelt und nicht viel geprüft/getestet. Mir ging es eher darum zu zeigen, dass man einiges an Ballast gegenüber der Rekursion los werden kann, und sich auch die Lesbarkeit erhöht (ich finde Rekursion immer sehr aufwändig nachzuvollziehen im Kopf).


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

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