AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi C++ zu Delphi - (Inverse Matrix) liefert falsches Ergebnis
Thema durchsuchen
Ansicht
Themen-Optionen

C++ zu Delphi - (Inverse Matrix) liefert falsches Ergebnis

Ein Thema von MisterNiceGuy · begonnen am 10. Jul 2009
Antwort Antwort
Benutzerbild von MisterNiceGuy
MisterNiceGuy

Registriert seit: 1. Jul 2003
Ort: Mannheim
919 Beiträge
 
Delphi 7 Personal
 
#1

C++ zu Delphi - (Inverse Matrix) liefert falsches Ergebnis

  Alt 10. Jul 2009, 01:02
Hi, ich habe gerade versucht eine Funktion von C++ in Delphi zu übersetzen. Leider liefert mir die Delphi-Übersetzung ein falsches Ergebnis
obwohl ich mir sicher bin alles richtig gemacht zu haben.

//edit: Gelöst, ich habe die repeat-Schleife einmal zu wenig durchlaufen -.- Der Code unten ist korrigiert und steht zur allgemeinen Verfügung bereit! P.S. C++ Quellcode ist von zeiner.at

Findet ihr den Fehler?

C++ Code:

Code:
int Inverse (double a[][NMAX], double ainv[][NMAX], int n)
{
  int  i, j;                   // Zeile, Spalte
  int  s;                      // Elimininationsschritt
  int  pzeile;                 // Pivotzeile
  int  fehler = 0;             // Fehlerflag
  double f;                     // Multiplikationsfaktor
  const double Epsilon = 0.01;  // Genauigkeit
  double Maximum;               // Zeilenpivotisierung
  extern FILE *fout;
  int pivot = 1;

  // ergänze die Matrix a um eine Einheitsmatrix (rechts anhängen)
  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++)
    {
      a[i][n+j] = 0.0;
      if (i == j)
        a[i][n+j] = 1.0;
    }
  }
  #if DEBUG
     MatOut (stdout, a, n, 2*n);
  #endif
 
  // die einzelnen Eliminationsschritte
  s = 0;
  do {
     // Pivotisierung vermeidet unnötigen Abbruch bei einer Null in der Diagnonalen und
      // erhöht die Rechengenauigkeit
    Maximum = fabs(a[s][s]);
    if (pivot)
    {
       pzeile = s ;
       for (i = s+1; i < n; i++)
         if (fabs(a[i][s]) > Maximum) {
           Maximum = fabs(a[i][s]) ;
           pzeile = i;
         }
    }
    fehler = (Maximum < Epsilon);

    if (fehler) break;          // nicht lösbar

    if (pivot)
    {
      if (pzeile != s) // falls erforderlich, Zeilen tauschen
      { double h;
        for (j = s ; j < 2*n; j++) {
          h = a[s][j];
          a[s][j] = a[pzeile][j];
          a[pzeile][j]= h;
        }
      }
    }

    // Eliminationszeile durch Pivot-Koeffizienten f = a[s][s] dividieren
    f = a[s][s];
    for (j = s; j < 2*n; j++)
      a[s][j] = a[s][j] / f;

    // Elimination --> Nullen in Spalte s oberhalb und unterhalb der Diagonalen
    // durch Addition der mit f multiplizierten Zeile s zur jeweiligen Zeile i
    for (i = 0; i < n; i++ ) {
      if (i != s)
      {
        f = -a[i][s];                // Multiplikationsfaktor
        for (j = s; j < 2*n ; j++)   // die einzelnen Spalten
          a[i][j] += f*a[s][j];      // Addition der Zeilen i, s
      }
    }
    #if DEBUG
      fprintf(stdout, "Nach %1i-tem Eliminationschritt:\n", s+1);
      MatOut (stdout, a, n, 2*n);
    #endif
    s++;
  } while ( s < n ) ;

  if (fehler)
  {
    fprintf (fout, "Inverse: Matrix ist singulär\n");
    return 0;
  }
  // Die angehängte Einheitsmatrix Matrix hat sich jetzt in die inverse Matrix umgewandelt
  // Umkopieren auf die Zielmatrix
  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
      ainv[i][j] = a[i][n+j];
    }
  }
  return 1;
}
Mein Delphi-Code:

Delphi-Quellcode:
function InverseMatrix(Matrix:TMatrix):TMatrix;
  var i,j,s,pzeile,fehler,n:integer;
      f,Maximum,h:double;
      tempMatrix:TMatrix;
  const Epsilon = 0.01;
begin
  //Using this matrix, we can only form the inverse element if height and
  //width are the same
  if length(Matrix) <> length(Matrix[0]) then
  begin
    result := nil;
    exit;
  end;

  fehler := 0;
  n := length(Matrix);
  setlength(result,n,n);
  setlength(tempmatrix,n,2*n);

  tempMatrix := AddIdentityMatrix(Matrix);

  //Elimination - gehe jede Zeile der Matrix durch...
  s := 0;
  repeat
  begin
    //Nimm den Betrag von Element [s][s]
    Maximum := abs(tempMatrix[s][s]);
    //Weise pzeile die aktuelle Zeile zu
    pzeile := s;
    for i := (s+1) to (n-1) do //gehe alle kommenden zeilen durch...
    begin
      if (abs(tempMatrix[i][s]) > Maximum) then //wenn der betrag des wertes in zeile i und Spalte s größer ist
                                                //als das aktuelle maximum dann weise das neue Maximum zu
                                                //und mache bei zeile i weiter
      begin
        Maximum := abs(tempMatrix[i][s]);
        pzeile := i;
      end;
    end;
    //Nun haben wir die Zeile mit dem höchsten Betrag an Stelle s

    //Wenn das Maximum kleiner als 0.01 ist, dann beende weil determinate 0 ist
    if Maximum < Epsilon then
    begin
      fehler := 1;
      break;
    end;

    //Nur wenn die Zeile mit dem höchsten Betrag an Stelle s nicht die Zeile s ist, dann tausche
    //alle Zahlen aus Zeile s mit Zeile pzeile
    if (pzeile <> s) then
    begin
      h := 0;
      for j := s to (2*n)-1 do //gehe alle zeichen in der aktuellen spalte durch
      begin
        h := tempMatrix[s][j]; //h := tempMatrix[s][j];
        tempMatrix[s][j] := tempMatrix[pzeile][j]; //tempMatrix[s][j] := tempMatrix[pzeile][j];
        tempMatrix[pzeile][j] := h; //tempMatrix[pzeile][j] := h;
      end;
    end;

    //Eliminationszeile durch Pivot-Koeffizienten f = Matrix[s][s] dividieren
    //...
    //Jetzt aus der Zeile mit unserem Maximum alle Werte durch den Wert an Stelle s teilen
    f := tempMatrix[s][s];
    for j := s to (2*n)-1 do
      tempMatrix[s][j] := tempMatrix[s][j] / f;


    // Elimination --> Nullen in Spalte s oberhalb und unterhalb der Diagonalen
    // durch Addition der mit f multiplizierten Zeile s zur jeweiligen Zeile i
    //...
    //Addiere in jeder Zeile - außer Zeile s - auf jedes Zeichen den wert [s][j]*f
    for i := 0 to n-1 do
    begin
      if( i <> s) then
      begin
        f := -tempMatrix[i][s];
        for j := s to (2*n)-1 do
          tempMatrix[i][j] := tempMatrix[i][j] + (f*tempMatrix[s][j]);
      end;
    end;

    //showmessage('blubb');

    showmessage('Schritt: '+inttostr(s));
    showmatrix(tempmatrix);
    inc(s);
  end until (s = n);

  if fehler = 1 then
  begin
    showmessage('Inverse: Matrix ist singulär!');
    exit;
  end;

  showmatrix(tempmatrix);
  // Die angehängte Einheitsmatrix Matrix hat sich jetzt in die inverse Matrix umgewandelt
  // Umkopieren auf die Zielmatrix
  for i := 0 to n-1 do
    for j := 0 to n-1 do
      result[i][j] := tempMatrix[i][j+n];
end;
P.S. Meine Funktion zum Hinzufügen der Identitätsmatrix funktioniert einwandfrei!
Jonas
Wenn mich jemand sucht, ich bin im Kühlschrank!

Informationen über das Duale Studium
www.jofre.de
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:12 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