Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Übergabe einer Matrix an Unterprogramm (https://www.delphipraxis.net/162458-uebergabe-einer-matrix-unterprogramm.html)

swarley 23. Aug 2011 20:46

Übergabe einer Matrix an Unterprogramm
 
Hallo,
ich habe das Unterprogramm zur Berechnung der Inversen soweit hingekriegt (nehm ich an). Dummerweise mache ich wohl etwas bei der Übergabe der Ausgangsmatrix bzw Übergabe der Ergebnismatrix falsch. Dabei brauch ich noch einmal Hilfe.

Ich habe in meiner ButtonInverse.Onclick procedure zeilen-und spaltengröße, sowie meine Matrix, die ich invertieren möchte eingelesen. Daraufhin habe ich eine Matrix erzeugt, welche so aussieht, dass im vorderen Teil meine Ausgangsmatrix steht und die Einheitsmatrix sozusagen im hinteren Teil angehangen wird.
Bsp:
|1 2 3 1 0 0|
|4 5 6 0 1 0| =: matgauss
|7 8 9 0 0 1|

dann rufe ich mein Unterprogramm "Inverse" auf mit folgendem Befehl:
Delphi-Quellcode:
Inverse(0, zeilen, spaltengauss, matgauss);
der Quelltext meines Unterprogramms sieht dabei so aus:
Delphi-Quellcode:
procedure Inverse(a,zeilen,spaltengauss:Integer;matgauss:TMatrixgauss);
var i,j,k : Integer;
begin
  if a < zeilen-1 then
  begin
      for i := a to spaltengauss - 1 do
       begin
         matgauss[a,i]:=matgauss[a,i]/matgauss[a,a];
       end;
      for j := a+1 to zeilen - 1 do
        begin
          for k := a to spaltengauss - 1 do
            begin
                matgauss[j,k]:=matgauss[j,k]-matgauss[j,a]*matgauss[a,k];
            end;
        end;
    Inverse(a+1,zeilen,spaltengauss,matgauss);
  end;
end;
so wenn ich das Programm starte, werden mir keine Fehler gemeldet. Wenn ich nun eine beliebige Matrix eingebe (angenommen, die obige, also
|1 2 3|
|4 5 6|
|7 8 9|,
dann wird mir leider nicht wie erhofft:
|1 0 0 x x x|
|0 1 0 x x x|
|0 0 1 x x x| (x steht hierbei für die invertierten werte)
ausgegeben, sondern:
|1 2 3 1 0 0|
|4 5 6 0 1 0|
|7 8 9 0 0 1|

also muss ich ja irgendwas bei der übergabe falsch gemacht haben, oder? Bitte schnellstens um Hilfe!

PS: eine Überprüfung und Korrektur, falls das erste Element in der matrix eine 0 sein sollte, habe ich vorgenommen und alle Fälle abgefangen(also sollte es nur eine zeile geben, weile im ersten element nicht 0 ist, bzw wenn alle elemente eine 0 enthalten usw)
es geht mir erst einmal nur allein darum, wenigstens eine korrekte ausgabe zu erhalten, sprich, dass mir ein stringgrid angezeigt wird in dem im vorderen teil die einheitsmatrix steht!

Bjoerk 23. Aug 2011 21:34

AW: Übergabe einer Matrix an Unterprogramm
 
Die rechte Seite brauchst du nicht zu übergeben, das kann Inverse erledigen.

Delphi-Quellcode:

type
  TMat = array of array of double;


function Reziproke(const A: TMat): TMat;
var
  N, I, J, K, L: integer;
  Q: double;
  G, B: TMat;
begin
  N:= Length(A);
  SetLength(G, N, N);
  SetLength(B, N, N);
  SetLength(Result, N, N);
  // Umspeichern, Rechte Seite setzen
  for I:= 0 to N-1 do
  begin
    for J:= 0 to N-1 do
    begin
      G[I, J]:= A[I, J];
      B[I, J]:= 0;
    end;
    B[I, I]:= 1;
  end;
  // Gauss mit N Rechten Seiten
  ..
  ..
end;

procedure TForm1.Button7Click(Sender: TObject);
var
  A, R: TMat;
  N, I, J: integer;
begin
  N:= 3;
  SetLength(A, N, N); // Matrix
  A[0, 0]:= 1; A[0, 1]:= 2; A[0, 2]:= 0;
  A[1, 0]:= 2; A[1, 1]:= 3; A[1, 2]:= 0;
  A[2, 0]:= 3; A[2, 1]:= 4; A[2, 2]:= 1;
  R:= Reziproke(A);
  // for I:= 0 to N-1 do for J:= 0 to N-1 do ShowMessage (FloatToStr(R[I, J]));
  SetLength(A, 0); // Matrix
  SetLength(R, 0); // Reziproke
end;

FredlFesl 24. Aug 2011 06:47

AW: Übergabe einer Matrix an Unterprogramm
 
Die letzten beiden SetLength'se kannste Dir sparen. Das macht Delphi schon von alleine.
Und wenn du dann noch aus einem 'TMat' z.B. ein 'TMatrix' machst, sieht das auch schon besser aus. Denn die Bezeichnung bzw. das Wort 'Mat' kenne ich einfach nicht.

swarley 24. Aug 2011 17:45

AW: Übergabe einer Matrix an Unterprogramm
 
so ich habe meinen algorithmus jetzt optimiert. und mein unterprogramm enthält folgenden Quelltext:
Delphi-Quellcode:
procedure Inverse(a,zeilen,spaltengauss:Integer;var matgauss:TMatrixgauss);
var i,j,k : Integer;
begin
  if a < zeilen-1 then
  begin
      for i := a to spaltengauss - 1 do
       begin
         matgauss[a,i]:=matgauss[a,i]/matgauss[a,a];
       end;
      for j := a+1 to zeilen - 1 do
        begin
          for k := a to spaltengauss - 1 do
            begin
              matgauss[j,k]:=matgauss[j,k]-matgauss[j,a]*matgauss[a,k];
            end;
        end;
    Inverse(a+1,zeilen,spaltengauss,matgauss);

    for j := a-1 downto 0 do
    matgauss[j,a]:=matgauss[j,a]-matgauss[j,a]*matgauss[a,a];
  end;
  for i := zeilen-1 to spaltengauss-1 do
    begin
       matgauss[zeilen-1,i]:=matgauss[zeilen-1,i]/matgauss[zeilen-1,zeilen-1];
        for j := a-1 downto 0 do
         matgauss[j,a]:=matgauss[j,a]-matgauss[j,a]*matgauss[a,a];
    end;
end;
mit der typdeklaration:
Delphi-Quellcode:
TMatrixgauss = array[0..5,0..10]of Double;
in meiner ButtonInverse.onClick procedure erstelle ich die matrix matgauss, die vor der übergabe, wie folgt aussieht:
|8 4 5 1 0 0|
|4 7 3 0 1 0| =: matgauss
|7 3 2 0 0 1|

Ich habe mehrmals überprüft, dass auch wirklich diese matrix in "matgauss" steckt, daher verstehe ich nicht wieso ich nach meinem prozeduraufruf
Delphi-Quellcode:
Inverse(0,zeilen,spaltengauss,matgauss);
, wenn ich eine 3 x 3 matrix eingebe, in meinem Stringgrid folgendes Ergebnis erhalte(zeilen hat den wert 3, spaltengauss 6)
|1 0 0 1 0 0|
|0 1 0 0 1 0|
|0 0 1 0 0 1|


anstatt:
|1 0 0 -0.05 -0.08 0.25|
|0 1 0 -0.14 0.20 0.04|
|0 0 1 0.40 -0.04 -0.43|

(gut das ist wegen den gebrochenen Zahlen jetzt ein doofes Beispiel, aber darum geht es ja nicht)
Kann mir jemand erklären, wieso mein algorithmus im "vorderen Teil" der Matrix arbeitet und im "hinteren" nicht?

Bjoerk 25. Aug 2011 00:34

AW: Übergabe einer Matrix an Unterprogramm
 
FredlFesl, TMat oder TMatrix, ist sowas von egal. Und die SetLength’s Null kann man sich nur bei lokalen Variablen schenken (ich schreib’s der Vollständigkeit halber gelegentlich dennoch hin).

swarley, wenn du die Variante möchtest, in der die Lösung auf der rechten Seite steht, dann kenn ich das so:

Delphi-Quellcode:
procedure Inverse(const N: integer; var A: TMatrixGauss);
var
  i,j,k : Integer;
begin
  for I:= 0 to N-1 do
    for J:= I+1 to N+N-1 do
    begin
      A[I, J]:= A[I, J] / A[I, I]; // Matrix singulär, falls A[I, I] = 0
      for K:= 0 to N-1 do
        if K <> I then A[K, J]:= A[K, J] - A[K, I] * A[I, J];
    end;
end;

procedure TForm1.Button11Click(Sender: TObject);
var
  A: TMatrixGauss;
  I, J, N: integer;
begin
  N:= 3;
  A[0, 0]:= 1; A[0, 1]:= 2; A[0, 2]:= 0; A[0, 3]:= 1; A[0, 4]:= 0; A[0, 5]:= 0;
  A[1, 0]:= 2; A[1, 1]:= 3; A[1, 2]:= 0; A[1, 3]:= 0; A[1, 4]:= 1; A[1, 5]:= 0;
  A[2, 0]:= 3; A[2, 1]:= 4; A[2, 2]:= 1; A[2, 3]:= 0; A[2, 4]:= 0; A[2, 5]:= 1;
  Inverse(N, A);
  for I:= 0 to N-1 do
    for J:= N to N+N-1 do ShowMessage (FloatToStr(A[I, J]));
end;

gammatester 25. Aug 2011 07:50

AW: Übergabe einer Matrix an Unterprogramm
 
Zitat:

Zitat von Bjoerk (Beitrag 1119440)
Delphi-Quellcode:
procedure Inverse(const N: integer; var A: TMatrixGauss);
//...
      A[I, J]:= A[I, J] / A[I, I]; // Matrix singulär, falls A[I, I] = 0
//...
end;

Der Kommentar ist falsch bzw. unsinnig/irreführend. Wenn A[I, I] gleich 0 ist, heißt das erstmal nur, daß man ohne Zeilenvertauschungen nicht weiter kommt. Selbstverständlich ist zB die folgende Matrix nicht singulär:
Code:
0 1
2 0

gammatester 25. Aug 2011 08:31

AW: Übergabe einer Matrix an Unterprogramm
 
Zitat:

Zitat von swarley (Beitrag 1119390)
Kann mir jemand erklären, wieso mein algorithmus im "vorderen Teil" der Matrix arbeitet und im "hinteren" nicht?

Ohne auf die merkwürdigen Interna dieser rekursiven Lösung einzugehen, hier ein Hinweis, warum es nicht funktionieren kann:
Zitat:

Zitat von swarley (Beitrag 1119390)
Delphi-Quellcode:
for i := a to spaltengauss - 1 do begin
  matgauss[a,i]:=matgauss[a,i]/matgauss[a,a];
end;

Was soll das bezwecken? Was es bewirkt, ist doch folgendes: matgauss[a,a] wird auf 1 gesetzt, der Rest wird durch 1 geteilt, bleibt also gleich. Eventuell hilft ja hier
Delphi-Quellcode:
for i :=spaltengauss - 1 downto a begin
  matgauss[a,i]:=matgauss[a,i]/matgauss[a,a];
end;
und an der anderen Stelle.(Warum wird eigentlich a=zeilen-1 aus der Rekursion ausgespart?) Dies aber ohne Garantie. Wenn jemand unbedingt, etwas völlig Unorthodoxes programmieren will...

Bjoerk 25. Aug 2011 10:43

AW: Übergabe einer Matrix an Unterprogramm
 
Zitat:

Zitat von gammatester (Beitrag 1119456)
Der Kommentar ist falsch bzw. unsinnig/irreführend. Wenn A[I, I] gleich 0 ist, heißt das erstmal nur, daß man ohne Zeilenvertauschungen nicht weiter kommt. Selbstverständlich ist zB die folgende Matrix nicht singulär:
Code:
0 1
2 0

Sorry Kumpel, im Sinne des Gauß Algorithmus ist diese Matrix singulär.

gammatester 25. Aug 2011 11:40

AW: Übergabe einer Matrix an Unterprogramm
 
Zitat:

Zitat von Bjoerk (Beitrag 1119528)
Zitat:

Zitat von gammatester (Beitrag 1119456)
Der Kommentar ist falsch bzw. unsinnig/irreführend. Wenn A[I, I] gleich 0 ist, heißt das erstmal nur, daß man ohne Zeilenvertauschungen nicht weiter kommt. Selbstverständlich ist zB die folgende Matrix nicht singulär:
Code:
0 1
2 0

Sorry Kumpel, im Sinne des Gauß Algorithmus ist diese Matrix singulär.

Entschuldigung, aber so eine hirnrissige Äußerung habe ich schon lange nicht mehr gelesen. Wenn Du wenigsten geschrieben hättest, im Sinne von Bjoerk ist diese Matrix singulär (vielleicht noch mit 'mem Smiley) hätte man es als harmlose Spinnerei nehmen können, so wie 42% schwanger.

Bjoerk 25. Aug 2011 16:52

AW: Übergabe einer Matrix an Unterprogramm
 
Bleib mal locker, kein Grund unfreundlich zu werden. Eine Matrix ist dann singulär, wenn sie keine Inverse hat. Mag sein, daß deine Matrix eine Inverse hat, man kann Sie aber nicht mit dem Gauß des TE berechnen, das war alles, was ich sagen wollte...


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:15 Uhr.
Seite 1 von 2  1 2      

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