Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   for-Schleife gegen über while-Schleife (https://www.delphipraxis.net/131246-schleife-gegen-ueber-while-schleife.html)

Luckie 21. Mär 2009 02:24


for-Schleife gegen über while-Schleife
 
Unser Lehrer hat heute gemeint, dass man es möglichst vermeiden sollte aus Schleifen zu springen. Und wenn es nötig sein sollte, sollte man es im Schleifenkopf machen, also eine while-Schleife nehmen.

Ich habe das jetzt mal ausprobiert:
Delphi-Quellcode:
function IsPLZInArray(SonnenStundenListe: TSonnenStunden; PLZ: Integer): Boolean;
var
  i: Integer;
  CurrentPLZ: Integer;
begin
  i := 0;
  Result := False;

  while (i < length(SonnenStundenListe) - 1) and (not Result) do
  begin
    CurrentPLZ := SonnenStundenListe[i, 0];
    Result := CurrentPLZ = PLZ;
    Inc(i);
  end;
end;
Delphi-Quellcode:
function IsPLZInArray(SonnenStundenListe: TSonnenStunden; PLZ: Integer): Boolean;
var
  i: Integer;
  CurrentPLZ: Integer;
begin
  i := 0;
  Result := False;

  for I := 0 to length(SonnenStundenListe) - 1 do
  begin
    CurrentPLZ := SonnenStundenListe[i, 0];
    if CurrentPLZ = PLZ then
    begin
      Result := True;
      Break;
    end;
  end;
end;
Also ich finde die for-Schleife leichter verständlich. Bei der while-Schleife habe ich fast einen Knoten ins Hirn bekommen, wegen der Abbruchbedingung. Das gilt für mich zumindest wenn es mehr als eine Abbruchbedingung gibt.

Was meint ihr?

Medium 21. Mär 2009 02:48

Re: for-Schleife gegen über while-Schleife
 
Das wesentliche Problem ist nur die Lesbarkeit. In deinem Beispiel müsste man zunächst den Kopf der zuletzt angeworfenen Schleife suchen um zu wissen was nun wo fortgesetzt wird. Da das Break in einem if-Block, also eine Ebene weiter eingerückt steht, kann man nicht einfach den Block als verlassenes Segment verstehen, sondern man muss u.U. eine ganze Serie von Block-Hierachien beachten.
Bei der while-Version steht gleich am Anfang "Pass mal auf, wenn das und jenes in der Schleife passiert, gehts einfach am Ende genau dieses Blocks weiter.
Das war dann aber auch schon alles, und ich erwische mich selbst auch oft genug dabei Break oder Continue zu verwenden, weil es im Schreibfluss finde ich leichter zu erdenken ist. In manchen Fällen gehe ich dann aber doch nachher noch mal an die Schleifen und baue sie um - einfach nur weil's schöner zu lesen ist, und unsere Programme teilweise auch noch nach 2-3 Jahren mit Änderungswünschen belegt werden, wo es dann doch ganz gut ist schnell zu verstehen was man sich damals so alles dabei gedacht hat =)

jaenicke 21. Mär 2009 03:58

Re: for-Schleife gegen über while-Schleife
 
Meine ganz klare Meinung: Die for-Variante ist in diesem Fall besser, weil vorher bekannt ist bis wo die Schleife maximal läuft.

Von der Lesbarkeit oder dem Schreiben des Codes ist das für mich persönlich kein großer Unterschied, sofern der Code ordentlich formatiert ist. Mehrfache Abbruchbedingungen benutze ich oft und die zu entwerfen ist auch kein Problem.

Der Grund ist ein anderer. Die for-Schleife kann vom Compiler sehr gut optimiert werden. Und der Zielwert ist bekannt und muss nicht jedesmal überprüft werden. Der Compiler kann ein passendes Register auswählen und die Zählweise optimieren. Das geht bei der While-Schleife nicht. Es muss jedesmal die vorgegebene Bedingung überprüft werden.
Ergebnis mit while:
Delphi-Quellcode:
Unit162.pas.36: i := 0;
004532C9 33F6             xor esi,esi
Unit162.pas.37: Result := False;
004532CB 33DB            xor ebx,ebx
004532CD EB0D            jmp $004532dc
Unit162.pas.41: CurrentPLZ := SonnenStundenListe[i];
004532CF 8B45FC          mov eax,[ebp-$04]
004532D2 8B3CB0           mov edi,[eax+esi*4]
Unit162.pas.42: Result := CurrentPLZ = PLZ;
004532D5 3B7DF8           cmp edi,[ebp-$08]
004532D8 0F94C3           setz bl
Unit162.pas.43: Inc(i);
004532DB 46               inc esi
Unit162.pas.39: while (i < length(SonnenStundenListe) - 1) and (not Result) do
004532DC 8B45FC          mov eax,[ebp-$04]
004532DF E84022FBFF      call @DynArrayLength   // !!! Wird jedesmal aufgerufen
004532E4 48               dec eax
004532E5 3BF0             cmp esi,eax
004532E7 7D04             jnl $004532ed
004532E9 84DB            test bl,bl
004532EB 74E2             jz $004532cf
Unit162.pas.45: end;
004532ED 33C0             xor eax,eax
Ergebnis mit for:
Delphi-Quellcode:
Unit162.pas.53: Result := False;
0045333E 33DB            xor ebx,ebx
Unit162.pas.55: for I := 0 to length(SonnenStundenListe) - 1 do
00453340 8B45FC          mov eax,[ebp-$04]
00453343 E8DC21FBFF      call @DynArrayLength  // !!! Wird nur einmal aufgerufen
00453348 48               dec eax        // überflüssig, siehe unten folgender Quelltext
00453349 85C0             test eax,eax
0045334B 7C15             jl $00453362
0045334D 40               inc eax
0045334E 33D2             xor edx,edx
Unit162.pas.57: CurrentPLZ := SonnenStundenListe[i];
00453350 8B4DFC          mov ecx,[ebp-$04]
00453353 8B3C91           mov edi,[ecx+edx*4]
Unit162.pas.58: if CurrentPLZ = PLZ then
00453356 3BF7             cmp esi,edi
00453358 7504             jnz $0045335e
Unit162.pas.60: Result := True;
0045335A B301             mov bl,$01
Unit162.pas.61: Break;
0045335C EB04             jmp $00453362
Unit162.pas.63: end;
0045335E 42               inc edx
Unit162.pas.55: for I := 0 to length(SonnenStundenListe) - 1 do
0045335F 48               dec eax
00453360 75EE            jnz $00453350
Unit162.pas.64: end;
00453362 33C0             xor eax,eax
Aus dem Grund ist die for-Schleife deutlich besser geeignet unter der Voraussetzung, dass man wie in diesem Fall vorher weiß wie lange die Schleife laufen soll (von der Abbruchbedingung abgesehen). In der Schleife muss dann hier in diesem Fall nur noch eine selbst geschriebene Bedingung ausgeführt werden.

Am optimalsten sieht das Ergebnis aus, wenn man direkt High benutzt, dann spart man auch noch das -1:
Delphi-Quellcode:
function IsPLZInArrayFor2(SonnenStundenListe: TSonnenStunden; PLZ: Integer): Boolean;
var
  i: Integer;
  CurrentPLZ: Integer;
begin
  Result := False;

  for I := 0 to High(SonnenStundenListe) do
  begin
    CurrentPLZ := SonnenStundenListe[i];
    if CurrentPLZ = PLZ then
    begin
      Result := True;
      Break;
    end;
  end;
end;
Delphi-Quellcode:
Unit162.pas.70: Result := False;
0045333E 33DB            xor ebx,ebx
Unit162.pas.72: for I := 0 to High(SonnenStundenListe) do
00453340 8B45FC          mov eax,[ebp-$04]
00453343 E8E421FBFF      call @DynArrayHigh
00453348 85C0             test eax,eax
0045334A 7C15             jl $00453361
0045334C 40               inc eax
0045334D 33D2             xor edx,edx
Unit162.pas.74: CurrentPLZ := SonnenStundenListe[i];
0045334F 8B4DFC          mov ecx,[ebp-$04]
00453352 8B3C91           mov edi,[ecx+edx*4]
Unit162.pas.75: if CurrentPLZ = PLZ then
00453355 3BF7             cmp esi,edi
00453357 7504             jnz $0045335d
Unit162.pas.77: Result := True;
00453359 B301             mov bl,$01
Unit162.pas.78: Break;
0045335B EB04             jmp $00453361
Unit162.pas.80: end;
0045335D 42               inc edx
Unit162.pas.72: for I := 0 to High(SonnenStundenListe) do
0045335E 48               dec eax
0045335F 75EE            jnz $0045334f
Unit162.pas.81: end;
00453361 33C0             xor eax,eax

Satty67 21. Mär 2009 05:49

Re: for-Schleife gegen über while-Schleife
 
Aus irgendeinem verstaubten Lehrbuch sitzt bei mir auch noch im Kopf: Kein Goto, Kein Break, Kein Exit

Also auch quasi die Aussage, wenn eine For-Schleife ein Break braucht, verwende While.

Ich halte mich schon lange nicht mehr daran, weil es richtig verwendet, nicht die Lesbarkeit zerstört. Man soll ja sowieso Schleifeninhalte möglichst klein halten, dann ist der Zusammenhang nicht weit auseinander gerissen. Mit etwas Erfahrung ist es selbst mir bei beiden Versionen leicht gefallen, den Sinn der Schleifen zu verstehen. Auch Exit am Funktions-Anfang, um sich eine weitere If-Ebene zu sparen, halten ich persönlich für Ok.

Die Beispiele von jaenicke fand ich jetzt auch sehr lehr- und aufschlussreich. Denn ohne mir Gedanken zu machen, hatte ich noch immer die Meinung, das While der For-Schleife in Sachen Geschwindigkeit überlegen ist. Das das falsch ist, sieht man so sehr schön. Auch der Vorteil von High() hätte ich nicht erwartet.

Btw: Macht die vorherige Zuweisung auf die lokale Variable CurrentPLZ überhaupt Sinn?

PS: Goto gehört natürlich trotzdem in kein Pascal-Code, war auch bei mir noch nie nötig.

Matze 21. Mär 2009 06:28

Re: for-Schleife gegen über while-Schleife
 
Unser Informatik-Professor rät auch ganz klar zur For-Schleife, wenn diese verwendet werden kann. Als Vorteile nannte er hauptsächlich, dass keine Endlosschleifen entstehen können und die Lesbarkeit oft einfacher ist. Trotz break oder continue.

Grüße, Matze

PS: Ein sehr kurzer Beitrag, aber man sieht mal die gegensätzlichen Meinungen von Dozenten.
PPS: Sebastians Beitrag ist wirklich interessant. Dass "High" (minimal) schneller ist als die "-1"-Variante, wusste ich nicht.

Luckie 21. Mär 2009 06:41

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Satty67
Btw: Macht die vorherige Zuweisung auf die lokale Variable CurrentPLZ überhaupt Sinn?

Kann ich nicht sagen. Es erhöht aber die Lesbarkeit und man kann es einfacher debuggen.

So, erst hatte ich meine for-Schleifen zu while-Schleifen gemacht und nach jaenickes Beitrag wieder zurück gebaut, weil er mich doch bestätigt hat. Da wären zum einem die technischen Gründe und dann noch die gefühlten Gründe, wie sie Satty67 erwähnt hat.

Aber einen hätte ich noch:
Delphi-Quellcode:
function GetNextLowerPLZFromList(var PLZ: Integer; PLZSunHours: TPLZSunHours): Integer;
begin
  // Raises EPLZNotInList exception if no lower PLZ can be found
  Result := PLZ;

  while (not IsPLZInList(PLZ, PLZSunHours)) and (PLZ <> -1) do
  begin
    Dec(PLZ);
    Result := PLZ;
  end;
  if PLZ = -1 then
    Raise EPLZNotInList.Create(rsENotInList);
end;
Mit
Delphi-Quellcode:
Type
  TPLZSunHours = array[0..4, 0..1] of Integer;

const
  PLZSunHours: TPLZSunHours = ((34126, 1200), (34127, 2100), (54123, 1000), (80459, 5210), (90785, 1500));
Ich denke, hier muss man eine while-Schleife nehmen. Aber die Abbruchbedingungen verursachen mir noch Kopfschmerzen. Das sieht irgendwie komisch bzw. umständlich aus.

Zur Aufgabe: Gegeben ist eine zwei dimensionale Liste mit PLZ Zahlen und Sonnenstunden pro Jahr. Nach Eingabe der Postleitzahl sollen die zugehörigen Sonnenstunden ausgegeben werden. Ist die PLZ nicht in der Liste, soll die nächst niedrigere genommen werden. Wird keine PLZ gefunden soll -1 ausgegeben werden. Aus der -1 habe ich eine Exception gemacht, aber das ist nebensächlich. (Das ist ein Aufgabe aus der Abschlussprüfung für Fachinformatiker. Dort sollte das allerdings nur in Pseudocode gelöst werden.)

Beim Schreiben des Codes habe ich mich versucht an die Regeln für sauberen Code zu halten, wie es in Clean Code dargestellt wird.

jaenicke 21. Mär 2009 07:16

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Luckie
Zitat:

Zitat von Satty67
Btw: Macht die vorherige Zuweisung auf die lokale Variable CurrentPLZ überhaupt Sinn?

Kann ich nicht sagen. Es erhöht aber die Lesbarkeit und man kann es einfacher debuggen.

Naja, es ist ein Assemblerbefehl mehr.
Code:
mov edi,[ecx+edx*4]
cmp esi,edi
Ohne die Zuweisung kann der Wert bei ecx+edx*4 auch direkt mit dem Wert im esi Register verglichen werden. Da aber meistens mehr mit der Variablen gemacht wird als ein simpler Vergleich, habe ich es so gelassen.

Denn meistens wird mehrfach auf den Eintrag im Array zugegriffen in der Schleife, was dann viel mehr Aufwand ist. Deshalb ist es meistens mit Zwischenvariable schon besser, also wollte ich das nicht ausgerechnet ansprechen, auch wenn es hier einen Assemblerbefehl mehr kostet.

Zitat:

Zitat von Luckie
Das sieht irgendwie komisch bzw. umständlich aus.

Ja, aber nicht unbedingt wegen der Bedingung. Du weist am Anfang doch ohnehin PLZ an Result zu. Wofür benutzt du danach denn trotzdem weiter PLZ und legst jedesmal wieder den neuen Wert in Result? ;-)
Delphi-Quellcode:
function GetNextLowerPLZFromList(var PLZ: Integer; PLZSunHours: TPLZSunHours): Integer;
begin
  // Raises EPLZNotInList exception if no lower PLZ can be found
  Result := PLZ;

  while (not IsPLZInList(Result, PLZSunHours)) and (Result <> -1) do
    Dec(Result);
  if Result = -1 then
    Raise EPLZNotInList.Create(rsENotInList);
end;
Sinnvoller wäre aber ja wohl eine Betrachtung des nächstkleineren Arrayeintrags statt alle Postleitzahlen durchzuprobieren.
Dafür müsstest du nur einmal dein Array durchgehen und alle vorhandenen Postleitzahlen betrachten. Das geht selbst bei einem unsortierten Array vermutlich schneller. Schließlich werden in deinem Array ja nicht so viele Postleitzahlen sein.

TheMiller 21. Mär 2009 09:46

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Luckie
Unser Lehrer hat heute gemeint, [...]

Morgen,

darf ich fragen, was du machst? Machst du eine Fortbildung oder sowas in der Art? Bei deinem Wissen, Deine Tuts und deine Non-VCL-Programme fällt mir es schwer zu glauben, dass du hier

a) von einem Lehrer im klassischen Sinne redest und
b) Dich ernsthaft mit den "Grundlagen" von Pascal beschäftigst.

Versteh mich nicht falsch, wenn dich deine Frage - zurecht - interessiert ist das ok. Mir ging es nur darum, dass du sagtest, dass dein Lehrer das meinte.

Wenn du magst, dann erzähl mir (oder uns) doch, was du momentan machst, und wofür du einen Lehrer hast, der dir Delphi erklärt ;)

Freundliche Grüße

Matze 21. Mär 2009 09:59

Re: for-Schleife gegen über while-Schleife
 
Schau hier:

Zitat:

Fachinformatiker / Anwendungsentwickler (2. Le(e/h)rjahr)
Stand: 09/2007

Dann wird es aktuell vermutlich das 3. und letzte Lehrjahr sein. ;)

Meflin 21. Mär 2009 12:44

Re: for-Schleife gegen über while-Schleife
 
Luckie, erlich gesagt habe ich keine Ahnung, was du für ein Problem mit derartigen Abbruchbedingungen in while-Schleifen hast ;)

Das ist ein absolutes Standardkonstrukt...

Nikolas 21. Mär 2009 13:01

Re: for-Schleife gegen über while-Schleife
 
Vielleicht sollte man auch den Wert von i nach Beendigung der Schleife in Betracht ziehen.

Bei der While Methode wird i inkrementiert, unabhängig davon, ob danach abgebrochen wird oder nicht.
Bei der for-schleife könnte man i direkt als Position des gefundenen Objekts benutzen.

wenn's um Lesbarkeit und minimale Geschwindigkeitsgewinne geht: wie wäre es mit
Delphi-Quellcode:
  for I := 0 to length(SonnenStundenListe) - 1 do
  begin
    if SonnenStundenListe[i, 0] = PLZ then
        return true;
  end;

Luckie 21. Mär 2009 13:09

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von jaenicke
Sinnvoller wäre aber ja wohl eine Betrachtung des nächstkleineren Arrayeintrags statt alle Postleitzahlen durchzuprobieren.
Dafür müsstest du nur einmal dein Array durchgehen und alle vorhandenen Postleitzahlen betrachten. Das geht selbst bei einem unsortierten Array vermutlich schneller. Schließlich werden in deinem Array ja nicht so viele Postleitzahlen sein.

:wall: Manchmal sieht man den Wald vor lauter Bäumen nicht. ;)


Zitat:

Zitat von Meflin
Luckie, erlich gesagt habe ich keine Ahnung, was du für ein Problem mit derartigen Abbruchbedingungen in while-Schleifen hast ;)

Das ist ein absolutes Standardkonstrukt...

Das ist es wohl, aber wie man sieht habe ich es mir unnötig schwer gemacht. Ich hatte also schon ein Gefühl, dass da was nicht gut ist. ;)

Zitat:

Zitat von DJ-SPM
Zitat:

Zitat von Luckie
Unser Lehrer hat heute gemeint, [...]

Morgen,

darf ich fragen, was du machst? Machst du eine Fortbildung oder sowas in der Art? Bei deinem Wissen, Deine Tuts und deine Non-VCL-Programme fällt mir es schwer zu glauben, dass du hier

a) von einem Lehrer im klassischen Sinne redest und

Ich mache eine Ausbildung zum Fachinformatiker anwendungsentwicklung. Also schon ein Lehrer im klassischen Sinne.

Zitat:

b) Dich ernsthaft mit den "Grundlagen" von Pascal beschäftigst.
Auch nach Jahren kann man sich noch mit den Grundlagn beschäftigen, dazu ist es nie zu spät.

Zitat:

Versteh mich nicht falsch, wenn dich deine Frage - zurecht - interessiert ist das ok. Mir ging es nur darum, dass du sagtest, dass dein Lehrer das meinte.
[..]
und wofür du einen Lehrer hast, der dir Delphi erklärt
Das mit den Schleifen ist ja nicht Delphi spezifisch. ;)

Win32.API 21. Mär 2009 13:09

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von jaenicke
[...]Am optimalsten sieht das Ergebnis aus, wenn man direkt High benutzt, dann spart man auch noch das -1 [...]

Das ist nur die halbe Warheit, denn eigentlich sieht das ganze dann so aus:

Code:
00453340 8B45FC          mov eax,[ebp-$04]
00453343 E8E421FBFF      call @DynArrayHigh
   @DynArrayHigh:
   00404E88 E8F3FFFFFF      call @DynArrayLength
   00404E8D 48               dec eax ; Da ist dein -1 wieder ;)
   00404E8E C3               ret
   00404E8F 90               nop
00453348 85C0             test eax,eax

Edith: Die man koennte length() noch optimieren:


length():
Delphi internes length()
Code:
length():
Ticks: ~9
MS: 3.35*10^-5

length__()
Wie das delphi interne length() nur ohne nil check

Delphi-Quellcode:
function Length__(var Obj):Integer;
asm
  mov eax, [eax - 4]
end;
Code:
length__():
Ticks: ~8
MS: 3.38*10^-5

length_()
Als inline variante

Delphi-Quellcode:
function Length_(var Obj):Integer; inline;
begin
  result := pDWord(DWord(Obj) - 4)^;
end;
Code:
length_():
Ticks: ~1
MS: 2.94*10^-5

omata 21. Mär 2009 13:24

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Luckie
Unser Lehrer hat heute gemeint, dass man es möglichst vermeiden sollte aus Schleifen zu springen. Und wenn es nötig sein sollte, sollte man es im Schleifenkopf machen, also eine while-Schleife nehmen.

Da habt ihr ja einen sehr guten Lehrer :thumb: :thumb:

sx2008 21. Mär 2009 13:53

Re: for-Schleife gegen über while-Schleife
 
Ich würde ich der For-Schleife sogar ein Exit anstelle eines Break verwenden (Natürlich nur wenn möglich).
Damit erreiche ich, dass das Register für Result möglichst lange dem Compiler für anderweitige
Benutzung zur Verfügung steht.
Delphi-Quellcode:
function IsPLZInArray(SonnenStundenListe: TSonnenStunden; PLZ: Integer): Boolean;
var
  i: Integer;
  CurrentPLZ: Integer;
begin
  for i := 0 to length(SonnenStundenListe) - 1 do
  begin
    CurrentPLZ := SonnenStundenListe[i, 0];
    if CurrentPLZ = PLZ then
    begin
      Result := True;
      Exit;
    end;
  end;
  Result := False; // nichts gefunden
end;

RWarnecke 21. Mär 2009 14:03

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von sx2008
Ich würde ich der For-Schleife sogar ein Exit anstelle eines Break verwenden (Natürlich nur wenn möglich).
Damit erreiche ich, dass das Register für Result möglichst lange dem Compiler für anderweitige
Benutzung zur Verfügung steht.
Delphi-Quellcode:
function IsPLZInArray(SonnenStundenListe: TSonnenStunden; PLZ: Integer): Boolean;
var
  i: Integer;
  CurrentPLZ: Integer;
begin
  for i := 0 to length(SonnenStundenListe) - 1 do
  begin
    CurrentPLZ := SonnenStundenListe[i, 0];
    if CurrentPLZ = PLZ then
    begin
      Result := True;
      Exit;
    end;
  end;
  Result := False; // nichts gefunden
end;

Wenn Du Dein Result := False vor die FOR-Schleife setzt, brauchst Du auch kein Exit und kannst das Preak drinlassen.

Keldorn 21. Mär 2009 14:48

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Luckie
Unser Lehrer hat heute gemeint, dass man es möglichst vermeiden sollte aus Schleifen zu springen. Und wenn es nötig sein sollte, sollte man es im Schleifenkopf machen, also eine while-Schleife nehmen.

es gehört jetzt zwar nicht ganz zum Thema ;-), aber ich finde es deprimierend, wenn sich ein Lehrer über die Verwendung einer for oder while-schleife Gedanken macht.
Auf der anderen Seite aber heute noch zuläßt, das eine PLZ als integer deklariert wird :wall:

Gruß Frank

sx2008 21. Mär 2009 14:57

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von RWarnecke
Wenn Du Dein Result := False vor die FOR-Schleife setzt, brauchst Du auch kein Exit und kannst das Preak drinlassen.

Das Result wird doch im Register EAX gehalten.
Indem man das Result so spät wie möglich zuweist, gibt man dem Compiler die Möglichkeit das Register frei zu verwenden.

jaenicke 21. Mär 2009 15:07

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Keldorn
Auf der anderen Seite aber heute noch zuläßt, das eine PLZ als integer deklariert wird :wall:

Naja, die Architektur ist 32-Bit, insofern ist es durchaus sinnvoll auch eine 32-Bit Zahl zu benutzen.

Ich glaube dazu stand auch etwas entsprechendes in der Delphi-Hilfe.

Meflin 21. Mär 2009 15:08

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von jaenicke
Naja, die Architektur ist 32-Bit, insofern ist es durchaus sinnvoll auch eine 32-Bit Zahl zu benutzen.

Die negative Zahlen als PLZ zulässt? Hm... nein, eigentlich nicht ;)

RWarnecke 21. Mär 2009 15:10

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von sx2008
Das Result wird doch im Register EAX gehalten.
Indem man das Result so spät wie möglich zuweist, gibt man dem Compiler die Möglichkeit das Register frei zu verwenden.

Was heißt das jetzt genau ? Wenn ich das Result := False am Anfang der Funktion setze, brauche ich mir keine Gedanken darm zu machen, muss ich jetzt Exit oder Break benutzen. Desweiteren finde ich den Code lesbarer und übersichtlicher.

Keldorn 21. Mär 2009 15:16

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von jaenicke
Zitat:

Zitat von Keldorn
Auf der anderen Seite aber heute noch zuläßt, das eine PLZ als integer deklariert wird :wall:

Naja, die Architektur ist 32-Bit, insofern ist es durchaus sinnvoll auch eine 32-Bit Zahl zu benutzen.

ich wohne in Sachsen, wir haben eine "016XX" als PLZ ;-). Das meine ich damit, daß eine PLZ nicht als Integer definiert werden sollte. Egal, wie, den Aufwand den Du betreiben mußt, die 0 irgendwo wieder herzuzaubern ist enorm. Wir bekommen heute noch Briefe, wo nur "16XX" drauf steht, und sowas sollte nicht vorkommen und wer weiß, wieviel schon falsch sortiert/ausgeliefert wurde.

sobald Du auch ans internationale denkst, gibts in den Nachbarländern genug Beispiele, die Buchstaben oder Leerzeichen in der PLZ enthalten haben.
Deswegen ist eine PLZ kein integer, sondern ein string und grad ein Lehrer sollte einem sowas beibringen ;-).

jaenicke 21. Mär 2009 15:35

Re: for-Schleife gegen über while-Schleife
 
Ja, es gibt ein paar Länder (weniger als 10 weltweit AFAIK), die andere Zeichen drin haben. Leider u.a. die USA.

Strings sind viel aufwendiger im Programm, deshalb lohnt es hier eher bei internationaler Software nach Ländern zu unterscheiden und nur in den wenigen Ländern tatsächlich die aufwendigen Stringoprationen zu benutzen. In dem Fall reichen Strings mit einer Länge von 10 Zeichen (USA).

Die führenden Nullen darf man natürlich nicht vergessen, aber bei einer Darstellung der gespeicherten Zahl ist das eigentlich klar.

Luckie 21. Mär 2009 15:58

Re: for-Schleife gegen über while-Schleife
 
Mir ging es eigentlich weniger um Laufzeitoptimierung, sondern eher um Optimierung in Richtung sauberen Code. Und die eigentliche Aufgabe ist auch eher nebensächlich.

Und das eine Poistleitzahl mit Null anfängt ist eher ein Problem der Post. Wenn die sich selber so eine Ausnahme eingabeut haben, müssen sie auch selber zu sehen, wie sie damit klar kommen. Aber das sollte nicht Thema hier sein.


Zitat:

Zitat von omata
Zitat:

Zitat von Luckie
Unser Lehrer hat heute gemeint, dass man es möglichst vermeiden sollte aus Schleifen zu springen. Und wenn es nötig sein sollte, sollte man es im Schleifenkopf machen, also eine while-Schleife nehmen.

Da habt ihr ja einen sehr guten Lehrer :thumb: :thumb:

Ich finde solche pauschalen Aussagen immer etwas bedenklich, wenn nicht sogar gefährlich. Ich denke, das ist immer Situations abhängig.

Meflin 21. Mär 2009 16:04

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Luckie
Und das eine Poistleitzahl mit Null anfängt ist eher ein Problem der Post. Wenn die sich selber so eine Ausnahme eingabeut haben, müssen sie auch selber zu sehen, wie sie damit klar kommen.

:shock: Das ist jetzt hoffentlich nicht dein ernst oder :shock: 0 ist ein ganzes PLZ-Gebiet und durchaus keine Ausnahme. Und du als Programmierer hast hier gefälligst dafür zu sorgen, dass man auch korrekt mit ihnen arbeiten kann, wenn du schon mit Postleitzahlen zu tun hast!

Das hat durchaus auch mit sauberem Code zu tun ;)

Luckie 21. Mär 2009 16:28

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Meflin
Zitat:

Zitat von Luckie
Und das eine Poistleitzahl mit Null anfängt ist eher ein Problem der Post. Wenn die sich selber so eine Ausnahme eingabeut haben, müssen sie auch selber zu sehen, wie sie damit klar kommen.

:shock: Das ist jetzt hoffentlich nicht dein ernst oder :shock:

Doch das ist mein Ernst. Die püostleitzahlen wurden zu einer Zeit neu vergeben, als Computer schon weit verbreitet waren. Man hätte sich also durchaus der Problematik bewusst sein können. Man hat aber mal wieder zu kurz gedacht. Und ich muss als Programmierer jetzt den Fehler der Post ausbügeln. Aber das gehört nicht hier her und ich will es acuh nicht weiter diskutieren. Ich muss erstmal eine Lampe aufhängen.

Satty67 21. Mär 2009 17:35

Re: for-Schleife gegen über while-Schleife
 
/Edit: will keine OT-Diskussion forcieren ;)

omata 21. Mär 2009 17:42

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Luckie
Ich finde solche pauschalen Aussagen immer etwas bedenklich, wenn nicht sogar gefährlich. Ich denke, das ist immer Situations abhängig.

Nein, da gibt es eine ganz einfache Regel: Wenn man eine Schleife vorzeitig beenden möchte, dann nimmt man niemals eine FOR-Schleife. Das ist ganz einfach und logisch.

jaenicke 21. Mär 2009 17:49

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von omata
Nein, da gibt es eine ganz einfache Regel: Wenn man eine Schleife vorzeitig beenden möchte, dann nimmt man niemals eine FOR-Schleife. Das ist ganz einfach und logisch.

Und was, wenn es auf die Laufzeit ankommt?
In den meisten Situationen mag es ja egal sein ob ein Schleifendurchlauf einige Rechentakte mehr braucht, aber was, wenn die Schleife millionenfach durchlaufen wird?

Klar: Soll der Benutzer halt warten, dafür ist er ja da...

Eine solche Pauschalisierung ist gefährlich. Man kann natürlich auch while-Schleifen versuchen zu optimieren, aber so einfach wie in diesem Fall ist das nicht immer.

quendolineDD 21. Mär 2009 17:54

Re: for-Schleife gegen über while-Schleife
 
Ich finde es durchaus ok, break oder exit zu verwenden. Gerade wenn man eine Zeit mit C programiert hat, merkt man, dass dies zumindest in C ein gängiger Programmierstil ist - und meiner Meinung nach nicht unbedingt ein "schlechter".
Im Großen und Ganzen würde ich meinen, sollte sich jeder seinen eigenen Stil aneignen und verwenden. In Zeiten der Mehrfachkernprozessoren macht es doch kaum noch Sinn, ob es nun 1 oder 8 Ticks sind, die solch eine banale Abfrage benötigt.

omata 21. Mär 2009 17:56

Re: for-Schleife gegen über while-Schleife
 
Das ist wirklich unwichtig, weil man niemals selber optimieren soll. Das ist das oberste Gebot im Compilerbau, optimiere niemals selbst. Dein Einwand ist doch nun wirklich super speziell. Ausnahmen bestätigen immer die Regel und die ist nunmal ganz einfach. Das ist genauso wie die Diskussion über die nicht zur strukturierten Programmierung gehörenden Befehle wie exit, break, continue, goto, label, ...
Die kann man bestimmt auch mal sinnvoll einsetzten, keine Frage, aber deshalb setzte ich sie nicht ständig ein. Sondern ich verwende sie vielleicht bei 1Mio. Programmzeilen 0,5mal. Ich habe sie noch nie in irgendeiner Anwendung benötigt, außer das exit, zu debug Zwecken.

Chemiker 21. Mär 2009 18:07

Re: for-Schleife gegen über while-Schleife
 
Hallo,

ich benutze die Schleife die das Problem am Schnellsten löst (für den Programmier). Sollte die Schleife zu einem schlechten Laufzeit verhalten führen, so muss an der Stelle eine Nachbesserung erfolgen. Vielleicht Denke ich da auch zu pragmatisch, weil die heutigen PCs doch recht schnell sind und die Millisekunden die ich einspare vom Betriebssystem wieder aufgefressen werden.

Bis bald Chemiker

Hansa 21. Mär 2009 18:24

Re: for-Schleife gegen über while-Schleife
 
@Luckie : höre besser auf deinen "Lehrer". Hier wird mehr auf break und sogar auf Exit gesetzt und das ist IMHO kein sauberer Stil. Man sehe sich mal diesen Source an :

Zitat:

Zitat von sx2008
Delphi-Quellcode:
function IsPLZInArray(SonnenStundenListe: TSonnenStunden; PLZ: Integer): Boolean;
var
  i: Integer;
  CurrentPLZ: Integer;
begin
  for i := 0 to length(SonnenStundenListe) - 1 do
  begin
    CurrentPLZ := SonnenStundenListe[i, 0];
    if CurrentPLZ = PLZ then
    begin
      Result := True;
      Exit;
    end;
  end;
  Result := False; // nichts gefunden
end;

Beim ersten gucken hat der mich schon 5 Sek. aufs Glatteis geführt. Zuerst habe ich das kleine "Exit" nicht gesehen (auch nicht erwartet) und dachte, was soll denn das, result wird ja so oder so auf false gesetzt. :shock: Nun ja, das sorgt ja lediglich dafür, dass alles danach kommende einfach ignoriert wird. Genau wie auch Break ist so was für mich quasi ein GOTO ohne Zeilennummern. Warum ist das nun meiner Meinung nach schlechter Stil ?

Erstens aus eigener Erfahrung. Bei meinem ersten größeren Programm habe ich auch überall Exit benutzt. Ist ja schön einfach und "lesbarer". Irgendwann hagelte es aber Quereffekte, die äußerst schwer nachzuvollziehbar waren. Habe solcherlei Konstrukte dann konsequent eliminiert. Dann kam auch noch ein Prof. und hat die Überflüssigkeit solcher Dinge demonstriert. Prinzipiell braucht man die wirklich nicht.

Das ist aber kein Dogma. Es gibt wohl sinnvolle Ausnahmen, aber die Regel sind die nie und nimmer. Register hin oder her. :mrgreen:

Ich bevorzuge jedenfalls Häuser mit einem Ein/Ausgang und nicht welche mit 10 versteckten Ausgängen. :gruebel:

jaenicke 21. Mär 2009 18:35

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von omata
Das ist wirklich unwichtig, weil man niemals selber optimieren soll. Das ist das oberste Gebot im Compilerbau, optimiere niemals selbst.

Beispiel:
Delphi-Quellcode:
  while (i < length(SonnenStundenListe) - 1) and (not Result) do
  begin
Delphi-Quellcode:
  for I := 0 to length(SonnenStundenListe) - 1 do
  begin
Hier ist while deutlich langsamer, weil bei for Length nur einmal aufgerufen wird, bei while jedoch mehrfach. Obwohl es fast gleich aussieht.
Will man hier also while sinnvoll benutzen, dann muss man das Ergebnis von Length zwischenspeichern und damit selbst optimieren, was der Compiler bei for bereits automatisch tut.

Zitat:

Zitat von Hansa
Ich bevorzuge jedenfalls Häuser mit einem Ein/Ausgang und nicht welche mit 10 versteckten Ausgängen. :gruebel:

Ich bevorzuge Häuser mit Notausgängen und Autobahnen mit Abzweigungen.

Nur weil die Autobahn von Berlin nach Hamburg geht, heißt das ja nicht, dass ich nicht zwischendurch abfahren darf. Trotzdem ist sie schneller als wenn ich solange (while ;-)) über Bundesstraßen in die Richtung fahre bis ich da bin.

Zitat:

Zitat von quendolineDD
In Zeiten der Mehrfachkernprozessoren macht es doch kaum noch Sinn, ob es nun 1 oder 8 Ticks sind, die solch eine banale Abfrage benötigt.

Sagten die Microsoft- und Firefox-Programmierer bei jedem "kleineren" Problem und wunderten sich, warum Chrome und Opera insbesondere beim Programmstart derart viel schneller sind. :roll:

Kleinvieh macht auch Mist. Wenn ich eine Abfrage habe, die 1 ms langsamer ist, weil man es nicht optimal geschrieben hat, dann ist das wenig. Habe ich dann davon 1000, dann ist das schon eine Sekunde...

Satty67 21. Mär 2009 18:44

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von Hansa
Beim ersten gucken hat der mich schon 5 Sek. aufs Glatteis geführt.

fand das auch unübersichtlich geschrieben:
Delphi-Quellcode:
function IsPLZInArray(SonnenStundenListe: TSonnenStunden; PLZ: Integer): Boolean;
var
  i: Integer;
begin
  Result := False;

  for i := 0 to length(SonnenStundenListe) - 1 do
  begin
    if SonnenStundenListe[i, 0] = PLZ then
    begin
      Result := True;
      Exit;
    end;
  end;

end;
Zitat:

Zitat von Hansa
Ich bevorzuge jedenfalls Häuser mit einem Ein/Ausgang und nicht welche mit 10 versteckten Ausgängen. :gruebel:

Denke eine Funktion sollte sowieso nicht 10 Schleifen enthalten...

Hansa 21. Mär 2009 18:49

Re: for-Schleife gegen über while-Schleife
 
Zitat:

Zitat von jaenicke
Ich bevorzuge Häuser mit Notausgängen und Autobahnen mit Abzweigungen....

Nene, das gilt nicht ! Abzweigungen = Sphagetticode. :mrgreen: Du fährst ja wohl kaum in Hamburg los und sagst einem, den du in Berlin treffen willst "wenn ich nicht da ankomme, dann hole mich bei irgendeiner Behelfsausfahrt ab, welche weiß ich aber noch nicht." :lol:

jaenicke 21. Mär 2009 18:55

Re: for-Schleife gegen über while-Schleife
 
Ein Beispiel ist dieser Code nach dem Prinzip eines endlichen Automaten:
http://www.delphipraxis.net/internal....php?p=1011376
Da würde mir zumindest auf Anhieb keine besonders übersichtliche Variante einfallen, die komplett auf das Herausspringen verzichtet. Das hätte da zu deutlich mehr Abfragen geführt.

Satty67 21. Mär 2009 19:04

Re: for-Schleife gegen über while-Schleife
 
Bei dem Aufbau der Funktionen innerhalb der Funktion und innerhalb der Funktion unterschiedlichen VAR Positionen hab' ich hier vor kurzem erst mit dem Rohrstock eines auf die Finger bekommen. :wink:

Hansa 21. Mär 2009 19:09

Re: for-Schleife gegen über while-Schleife
 
Knackpunkt ist allerdings tatsächlich die Ende-Bedingung :

Zitat:

Zitat von Luckie
Delphi-Quellcode:
while (i < length(SonnenStundenListe) - 1) and (not Result) do
  begin
    CurrentPLZ := SonnenStundenListe[i, 0];
    Result := CurrentPLZ = PLZ;
    Inc(i);
  end;
end;

Ist zwar hier ziemlich einfach, aber ich entflechte das lieber trotzdem so ungefähr :

Delphi-Quellcode:
ende := result;
if not ende then
  ende := not (i < length(SonnenStundenListe) - 1);
while not ende do begin
  CurrentPLZ := SonnenStundenListe[i, 0];
  Result := CurrentPLZ = PLZ;
  Inc(i);
...
end;
Wem 20 Nanosek. wichtiger sind, als seine eigene Programmlogik, der soll meinetwegen sogar auf die eine Variable verzichten. :zwinker:

oki 21. Mär 2009 20:32

Re: for-Schleife gegen über while-Schleife
 
Hi Leute,

auch wenn die Frage jetzt blöd klingt, aber kann mir mal einer sagen warum Break oder Exit jetzt so schlimm in Schleifen sind? Ich geb ehrlich zu, dass ich Break recht häufig verwende. Ich mag while nicht so richtig. Bis jetzt wurde nur von gutem Stil und lesbarkeit gesprochen. Eine fachliche Begründung hab ich noch nicht gesehen (oder überlesen). Ich geb auch ehrlich zu, dass ich vorrangig aus alter Gewohnheit For-Schleifen mit Break anstatt while-Schleifen verwende. Die while-Schleifen fallen eigentlich auch nicht viel schwerer. Hab mir bis jetzt mit Break und Exit nichts gedacht.

Also, was passiert denn nun so schlimmes bei Break und Exit in Schleifen?

Gruß oki


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:43 Uhr.
Seite 1 von 3  1 23      

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