Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi [gelöst] Wie oft wird diese Schleife durchlaufen? (https://www.delphipraxis.net/158429-%5Bgeloest%5D-wie-oft-wird-diese-schleife-durchlaufen.html)

asq81 17. Feb 2011 10:16


[gelöst] Wie oft wird diese Schleife durchlaufen?
 
Hallo!

ich fühle mich langsam etwas dumm =)
denn ich kann meinen Denkfehler einfach nicht entdecken, in dieser doch recht simpel anmutenden Schleife...
Bitte seht euch dies mal an:

Im folgenden Code wird der Index 'LASDidx' immer wieder mal zu gross. Grösser als der MAx-Index der vom SetLenght(...) kommt, was eigentlich nicht passieren sollte, da der Parameter 'LHelper' im SetLenght-Aufruf doch der Zahl der Durchläufe in der Schleife entsprechen sollte, oder nicht?
(offensichtlich nicht, denn da tritt ja der Fehler auf, ich finde dessen Ursache aber leider einfach nicht)


Delphi-Quellcode:
procedure Raster;
var
  i, k, iX, iY, LStartX, LEndX, LStartY, LEndY: Integer;
  LASD: array of TSDResult;
  LSDValue: Int64;
  LASDidx: Integer;
  LStep: Integer;
  LHelper: Integer;
  LOffX, LOffY: Integer;
begin

  LStep := 64; // oder irgendein anderes 2^n
  LStartX := 0; // anfangs immer 0
  LEndX := 1000; // immer > LStartX
  LStartY := 0; // mit Y wie bei X
  LEndY := 570;

  Repeat
    LASSDidx := 0;

    LHelper := Trunc(((LEndX-LStartX)*(LEndY-LStartY))/Sqr(LStep))+1; // +1 wegen Trunc()
    SetLength(LASD, LHelper);

    iX := LStartX;
    while iX <= LEndX do
    begin
      iY := LStartY;
      while iY <= LEndY do
      begin
        LASD[LASDidx].X := iX;
        LASD[LASDidx].Y := iY;
        Inc(LASDidx);

        if LASDidx >= High(LASD) then
// dieser If Block ist zum debuggen eingefügt
// hier habe ich einen Haltepunkt um zu sehen wann der Index out of Bounds geht
          showmessage(IntToStr(LASDidx)+ ' / ' + IntToStr(High(LASD)));

        iY += LStep;
      end;
      iX += LStep;
    end;

   // folgend wird ein zufälliger LOffX und LOffY gewählt
   // welche innerhalb oder auf den Grenzen (LStart../LEnd..)liegen
   // FMaxWidth und FMaxHeight sind konstante Werte die anfangs immer
   // grösser als LEndX bzw. LEndY sind
 
    LHelper := LOffX - LStep;
    if LHelper >= 0 then LStartX := LHelper else LStartX += 1;

    LHelper := LOffX + LStep;
    if LHelper <= FMaxWidth then LEndX := LHelper else LEndX -= 1;

    LHelper := LOffY - LStep;
    if LHelper >= 0 then LStartY := LHelper else LStartY += 1;

    LHelper := LOffY + LStep;
    if LHelper <= FMaxHeight then LEndY := LHelper else LEndY -= 1;

    // raster enger ziehen
    LStep := LStep div 2;

  until LStep = 0;

end;
Danke für eure Mühe!

lg
asq81

edit: paar Rechtschreib- u. Tippfehler korrigiert
edit2: Danke @WM_CLOSE! ich fand den code auch zu unbunt =) ([ CODE ] zu [ DELPHI ] geändert)

mkinzler 17. Feb 2011 10:24

AW: Wie oft wird diese Schleife durchlaufen?
 
Funktioniert den das?
Delphi-Quellcode:
iY += LStep;
Das ist doch eher c.

WM_CLOSE 17. Feb 2011 10:33

AW: Wie oft wird diese Schleife durchlaufen?
 
Lazarus?
Benutze bitte unbedingt den Delphi-Tag (den mit dem Römerhelm)
Dann sieht der Code übersichtlicher aus

jobo 17. Feb 2011 10:39

AW: Wie oft wird diese Schleife durchlaufen?
 
Was ist mit

Delphi-Quellcode:
LASSDidx
und
Delphi-Quellcode:
LASDidx
?

asq81 17. Feb 2011 10:45

AW: Wie oft wird diese Schleife durchlaufen?
 
Zitat:

Zitat von mkinzler (Beitrag 1082416)
Funktioniert den das?
Delphi-Quellcode:
iY += LStep;
Das ist doch eher c.

Richtig, ich benutze Lazarus da geht es
(hatte zuvor die a := a + b; Schreibweise, aber der Fehler bleibt an selber Stelle)

Zitat:

Zitat von jobo (Beitrag 1082419)
Was ist mit

Delphi-Quellcode:
LASSDidx
und
Delphi-Quellcode:
LASDidx
?

ist nur ein Schreibfehler, ich habe ein paar Codeteile vereinfacht dargestellt, der Übersichtlichkeit halber, muss dabei passiert sein (die weggelassenen Teile sind bei mir im Original auskommentiert, haben also keinen Einfluss)

edit: @jo: wo siehst du den Schreibfehler? Ich glaube ich habe den bereits korrigiert? =)

JasonDX 17. Feb 2011 11:09

AW: Wie oft wird diese Schleife durchlaufen?
 
Ich würde folgendes korrigieren:
Delphi-Quellcode:
LHelper := Trunc(((LEndX-LStartX)*(LEndY-LStartY))/Sqr(LStep))+1; // +1 wegen Trunc()
zu
Delphi-Quellcode:
LHelper := ceil((LEndX - LStartX) / LStep) * ceil((LEndY - LStartY) / LStep);
Zur Erklärung zu deinem Beispiel: Die X-Schleife wird 16 mal durchlaufen, die Y-Schleife 9 mal. Folglich greifst du auf 144 Elemente zu.
LHelper wird aber anders berechnet: 1000/64 = 15.625, 770/64 = 8.90625. Das Produkt daraus wird aber 139.16..., entsprechend bekommt das Array nur 140 Elemente. Es muss vor dem Multiplizieren gerunden werden.

greetz
Mike

asq81 17. Feb 2011 11:40

AW: Wie oft wird diese Schleife durchlaufen?
 
:wall:
ich benutze jetzt das Äquivalent: (weil Lazarus offenbar kein Ceil() kennt)
Delphi-Quellcode:
LHelper := Trunc(((LEndX-LStartX)/LIterationPixelStep)+1)
         * Trunc(((LEndY-LStartY)/LIterationPixelStep)+1);
(Liefert nun immer exakte Menge an benötigten Elementen)

Super! Danke vielmals!! =)

gammatester 17. Feb 2011 12:07

AW: Wie oft wird diese Schleife durchlaufen?
 
Zitat:

Zitat von asq81 (Beitrag 1082435)
:wall:
ich benutze jetzt das Äquivalent: (weil Lazarus offenbar kein Ceil() kennt)

Würde mich allerdings stark wundern! Jedenfalls hat FPC
Delphi-Quellcode:
function ceil(x: float) : Integer
in unit math (genau wie Delphi).

asq81 17. Feb 2011 13:13

AW: Wie oft wird diese Schleife durchlaufen?
 
Stimmt, ist in Math mit drin, wusste ich nicht. Danke! =)


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:50 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