Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fehler beim Einsatz von Schleife (https://www.delphipraxis.net/90061-fehler-beim-einsatz-von-schleife.html)

felxi 11. Apr 2007 00:08


Fehler beim Einsatz von Schleife
 
Hallo,

ich programmiere zur Zeit ein "game of life", welches auch fehlerfrei läuft. Mit einer Prozedur ermittle ich alle benachbarten Felder eins Feldes Feld[x|y], wobei 'k' die Anzahl der bisherigen Nachbarn ist:

Delphi-Quellcode:
 If Feld[x,y+1] = 1 then inc(k,1);
  If Feld[x+1,y+1] = 1 then inc(k,1);
  If Feld[x+1,y] = 1 then inc(k,1);
  If Feld[x+1,y-1] = 1 then inc(k,1);
  If Feld[x,y-1] = 1 then inc(k,1);
  If Feld[x-1,y-1] = 1 then inc(k,1);
  If Feld[x-1,y] = 1 then inc(k,1);
  If Feld[x-1,y+1] = 1 then inc(k,1);
So klappt alles einwandfrei, doch wenn ich dasselbe mit einer Schleife lösen will, kappts irgendwie nicht mehr :wiejetzt:

Delphi-Quellcode:
  For i := x-1 to x+1 do
    For j := y-1 to y+1 do
      If (i<>x)and(j<>y)and(Feld[i,j] = 1) then inc(k,1);
Finde den Fehler nicht :gruebel:

3_of_8 11. Apr 2007 00:15

Re: Fehler beim Einsatz von Schleife
 
Sieht auf den ersten Blick richtig aus, was genau geht denn nicht?

felxi 11. Apr 2007 00:43

Re: Fehler beim Einsatz von Schleife
 
Hier nochmal die ganze Prozedur:

Delphi-Quellcode:
procedure p_Nachbarn(x,y:integer);
var i,j,k:integer;
begin
  k := 0;
{ das funktioniert
 If Feld[x,y+1] = 1 then inc(k,1);
  If Feld[x+1,y+1] = 1 then inc(k,1);
  If Feld[x+1,y] = 1 then inc(k,1);
  If Feld[x+1,y-1] = 1 then inc(k,1);
  If Feld[x,y-1] = 1 then inc(k,1);
  If Feld[x-1,y-1] = 1 then inc(k,1);
  If Feld[x-1,y] = 1 then inc(k,1);
  If Feld[x-1,y+1] = 1 then inc(k,1); }

  For i := x-1 to x+1 do
    For j := y-1 to y+1 do
      If (i<>x)and(j<>y)and(Feld[i,j] = 1) then inc(k,1);

  Nachbarn := k;
end;
Ich habe gerade mal ein kleines Array mit Nullen gefüllt, bis auf die Felder [1,1][2,1][3,1], diese mit einer 1;

Die einzelne Abfrage hat mir für das Feld[2,2] 3 zurückgegeben - was korrekt ist, die Schleife aber nur 2.

DelphiProgrammierer 11. Apr 2007 01:30

Re: Fehler beim Einsatz von Schleife
 
Zitat:

Zitat von 3rdnuss
Hier nochmal die ganze Prozedur:

Delphi-Quellcode:
 If (i<>x)and(j<>y)and(Feld[i,j] = 1) then inc(k,1);

Hi 3rdnuss,
der Fehler liegt in der if Bedingung. Damit schließt Du alle Fälle aus mit
Feld[x,irgendwas] und Feld[irgendwas,y] also z.B. Feld[x,y+1] usw.

schreibe stattdessen:
Delphi-Quellcode:
if (not ((i=x) and (j=y))) and (Feld[i,j]=1) then inc(k,1);
Gruß


Ulrich

felxi 11. Apr 2007 09:32

Re: Fehler beim Einsatz von Schleife
 
ahh, danke, war wohl schon ein wenig zu spät :zwinker:

3_of_8 11. Apr 2007 10:16

Re: Fehler beim Einsatz von Schleife
 
Delphi-Quellcode:
if (not ((i=x) and (j=y))) and (Feld[i,j]=1) then inc(k,1);
Das lösen wir jetzt noch schön auf, nach den De-Morgan'schen Regeln:

Delphi-Quellcode:
if (i<>x) or (j<>y) and (Feld[i,j]=1) then inc(k,1);

Hawkeye219 11. Apr 2007 10:28

Re: Fehler beim Einsatz von Schleife
 
Die ursprüngliche Logik sollte man aber erhalten:

Delphi-Quellcode:
// if (i<>x) or (j<>x) and (Feld[i,j]=1) then inc(k,1);
if ((i <> x) or (j <> y)) and (Feld[i, j] = 1) then
  Inc (k);
Gruß Hawkeye

3_of_8 11. Apr 2007 10:31

Re: Fehler beim Einsatz von Schleife
 
Das j=x war ein Tippfehler, aber das andere stimmt schon so. Or bindet genauso stark wie and, und wenn keine Unterschiede in der Bindungsstärke da sind, wird einfach von links nach rechts abgearbeitet, daher brauchst du das ganze nicht zu klammern.

Hawkeye219 11. Apr 2007 10:39

Re: Fehler beim Einsatz von Schleife
 
Hallo Manuel,

Zitat:

Zitat von 3_of_8
Das j=x war ein Tippfehler, aber das andere stimmt schon so. Or bindet genauso stark wie and, und wenn keine Unterschiede in der Bindungsstärke da sind, wird einfach von links nach rechts abgearbeitet, daher brauchst du das ganze nicht zu klammern.

AND gilt als Multiplikation und bindet damit stärker als OR, das vergleichbar mit einer Addition ist.

Gruß Hawkeye

3_of_8 11. Apr 2007 11:15

Re: Fehler beim Einsatz von Schleife
 
Kommt drauf an. In der Rechnerarchitektur wird es oft so gesehen, in der Aussagen- und Prädikatenlogik sind and und or gleich stark bindend. In Delphi übrigens auch, habs grade ausprobiert.

Hawkeye219 11. Apr 2007 12:51

Re: Fehler beim Einsatz von Schleife
 
Zitat:

Zitat von 3_of_8
Kommt drauf an. In der Rechnerarchitektur wird es oft so gesehen, in der Aussagen- und Prädikatenlogik sind and und or gleich stark bindend. In Delphi übrigens auch, habs grade ausprobiert.

Ich verlasse mich darauf:

Zitat:

Zitat von Delphi-Hilfe
Code:
Operator                            Rangfolge
@, not                              Erste (höchste)
*, /, div, mod, and, shl, shr, as   Zweite
+, –, or, xor                       Dritte
=, <>, <, >, <=, >=, in, is         Vierte (niedrigste)
Ein Operator mit einer höheren Rangfolge wird vor einem Operator mit einer niedrigeren Rangfolge ausgewertet. Operatoren mit gleicher Rangfolge werden von links nach rechts ausgewertet.

Hier ist mein Testprogramm:

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  a, b, c : Boolean;

begin
  WriteLn;
  WriteLn ('X = a or b and c');
  WriteLn ('Y = (a or b) and c');
  WriteLn ('Z = a or (b and c)');
  WriteLn;
  WriteLn ('abc X Y Z');
  WriteLn ('----------');
  for a := False to True do
    for b := False to True do
      for c := False to True do
        WriteLn (Format('%d%d%d %d %d %d', [Ord(a), Ord(b), Ord(c),
                                             Ord(a or b and c),
                                             Ord((a or b) and c),
                                             Ord(a or (b and c))]));
end.
Gruß Hawkeye

DelphiProgrammierer 11. Apr 2007 14:06

Re: Fehler beim Einsatz von Schleife
 
Zitat:

Zitat von 3_of_8
Delphi-Quellcode:
if (not ((i=x) and (j=y))) and (Feld[i,j]=1) then inc(k,1);
Das lösen wir jetzt noch schön auf, nach den De-Morgan'schen Regeln:

Delphi-Quellcode:
if (i<>x) or (j<>y) and (Feld[i,j]=1) then inc(k,1);

Erstmal finde ich Deine Anmerkung prima.

Zweitens: Ich würde zusätzlich klammern bei Deiner Lösung, egal, wie die Bindungsregeln nun zufällig sind.

Drittens: Ich finde meine Lösung weiterhin anschaulicher.
Symbolisch lautet meine Lösung ja:
if (not Ausnahmefall) and (Feld[i,j]=1) then inc(k,1);
der Ausnahmefall wird aufgelöst als ((i=x) and (j=y))).

Bei Deiner Lösung muss man (ich jedenfalls) kurz nachdenken (letztlich versteckst Du das not in das <>).

3_of_8 11. Apr 2007 14:33

Re: Fehler beim Einsatz von Schleife
 
Okay, Hawkeye, du hast offenbar Recht. Die Ausgabe meines Testprogramms hab ich offenbar falsch interpretiert. Außerdem bin ich es aus der Mathematik gewöhnt, dass die Konjunktion so stark bindet wie die Disjunktion, die Implikation und Äquivalenz weniger stark und die Negation am stärksten.


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