Matrix invertieren c++ mit algorithmus



  • warum invertiert mir das Programm keine matrix bzw zeigt es nicht an?

    der Fehler muss an der Berechnung liegen...
    es erstellt die Matrix, zeigt sie an und fragt auch nach der richtigen eingabe der matrix, nur die inverse berechnet es nicht.... 😕

    #include "stdafx.h"
    #include <cmath>
    #include "windows.h"
    
    float matrix[20][20];
    float invmatrix[20][20];
    
    int main()
    {
    	int n = 1; //Dimension der Matrix
    	int iFehler = 0; //Fehlermerker
    	int iNochmal = 0;//Wiederholen oder beenden
    	int iRichtig = 0;//Überprüfung Matrix richtig
    	int i; //Zeilen Matrix 
    	int j;//Spalten Matrix
    	int k; 
    	int z;//Zeilenwechsel
    	float A[20][20];//Speichermatrix (array)
    
    	printf("------------------------------------ \n MATRIZEN INVERTIEREN \n------------------------------------ \n");
    	do
    	{
    		iFehler = 0;
    		printf("\n Dies ist ein Programm zum invertieren von Matrizen \n");
    		printf("\n Gib dafuer bitte eine Dimension n (fuer eine quadratische Matrix) zwischen 2 und 10 ein:\n n=");
    		scanf_s("%i", &n); //Dimension der Matrix erfassen
    		if (n< 2 || n > 10)
    		{
    			iFehler = 1;
    			printf("Fehler! Deine eingegebene Dimension ist nicht zwischen 2 und 10!  \n \nNochmal? \n \n 1. Ja \n 2.Nein \n --> ");
    			scanf_s("%i", &iNochmal);
    		} //if Fehlerschleife falsche Dimension
    		if (iFehler == 0)
    		{
    			printf(" \nGib nun zeilenweise die Matrix ein, die du invertieren willst und bestätige jedes Element mit Enter! \n", n, n);
    			//Eingabe der Matrix
    			for (i = 0; i < n; i++)
    			{
    				for (j = 0; j < n; j++)
    				{
    					scanf_s("%f", &matrix[i][j]);
    				}//for j
    			}//for i
    			printf("\nDeine Matrix lautet [%i][%i]... \n", n, n);
    			for (i = 0; i < n; i++)
    			{
    				for (j = 0; j < n; j++)
    				{
    					printf("\t%g", matrix[i][j]);
    				}//for j
    				printf("\n\n");
    			}//for i
    
    			printf("\n Ist deine Matrix richtig?\n \n 1. Ja \n 2. Nein \n");
    			scanf_s("%i",&iRichtig);
    
    			if (iRichtig == 1)
    			{
    				printf("\n Nun wird deine inverse Matrix berechnet:\n");
    				// Gauß-Algorithmus.
    				for (k = 0; k < n - 1; k++)
    				{
    					// Zeilen vertauschen, falls das Pivotelement eine Null ist
    					if (A[k][k] == 0)
    					{
    						for (i = k + 1; i < n; ++i)
    						{
    							if (A[i][k] != 0)
    							{
    								z<n, 2 * n>(A, k, i);
    								break;
    							}
    							else if (i == n - 1)
    								return false; // Es gibt kein Element != 0
    						}
    					}
    
    					// Einträge unter dem Pivotelement eliminieren
    					for (i = k + 1; i < n; ++i)
    					{
    						double p = A[i][k] / A[k][k];
    						for (j = k; j < 2 * n; ++j)
    							A[i][j] -= A[k][j] * p;
    					}
    				}
    
    				// Determinante der Matrix berechnen
    				double det = 1;
    				for (k = 0; k < n; k++)
    					det *= A[k][k];
    
    				if (det == 0)// Determinante ist =0 -> Matrix nicht invertierbar
    					printf("Die Matrix ist nicht invertierbar");
    					return false;
    
    				// Jordan-Teil des Algorithmus durchführen
    				for (k = n - 1; k > 0; k--)
    				{
    					for (int i = k - 1; i >= 0; i--)
    					{
    						double p = A[i][k] / A[k][k];
    						for (j = k; j < 2 * n; j++)
    							A[i][j] -= A[k][j] * p;
    					}
    				}
    
    				// Einträge in der linker Matrix auf 1 normieren und in invmatrix schreiben
    				for (i = 0; i < n; i++)
    				{
    					const double f = A[i][i];
    					for (j = n; j < 2 * n; j++)
    						invmatrix[i][j - n] = A[i][j] / f;
    				}
    				printf("\nDeine inverse Matrix lautet [%i][%i]... \n", n, n);//inverse Matrix ausgeben
    				for (i = 0; i < n; i++)
    				{
    					for (j = 0; j < n; j++)
    					{
    						printf("\t%g", invmatrix[i][j-n]);
    					}//for j
    					printf("\n\n");
    				}//for i
    			}//if Berechnung inverse Matrix
    
    			printf("\n \nNochmal? \n \n 1. Ja \n 2. Nein \n  ");
    			scanf_s("%i", &iNochmal);
    		} //if Nur weiterrechnen wenn Eingabe richtig
    	} while (iNochmal == 1); //while 
    
    	if (iNochmal == 2)
    	{
    		printf("\n---------------------------------- \n Vielen Dank und auf Wiedersehen! \n---------------------------------- \n \n Beende Anwendung...");
    		Sleep(1500);
    		return 0;
    	}// if
    
    	int iWait;//Warteschleife
    	scanf_s("%i", &iWait);
    	return 0;
    }
    


  • Benutze einen Debugger!

    for (j = n; j < 2 * n; j++)
                            invmatrix[i][j - n] = A[i][j] / f;
    

    Du hast eine n*n Matrix, lässt den Index aber von n bis 2*n laufen?

    float A[20][20];//Speichermatrix (array)
    

    Die Größe des Arrays ist fest, dann aber kann man die eigentliche Größe eingeben?

    Ich sehe irgendwie keinen Fetzen C++ in deinem Programm.



  • hmm.. ja leider hab ich da auch nicht so den plan von muss es nur leider machen..
    hast du vielleicht einen alternativen quellcode für den Algorithmus zur Berechnung der inversen Matrix?


  • Mod

    z<n, 2 * n>(A, k, i);
    

    was soll diese Zeile bewirken?



  • Zeilen vertauschen, falls das Pivotelement eine Null ist

    z<n, 2 * n>(A, k, i);
    


  • JJc schrieb:

    hast du vielleicht einen alternativen quellcode für den Algorithmus zur Berechnung der inversen Matrix?

    Klar

    // Returns the inverse of matrix `M`.
    function matrix_invert(M){
        // I use Guassian Elimination to calculate the inverse:
        // (1) 'augment' the matrix (left) by the identity (on the right)
        // (2) Turn the matrix on the left into the identity by elemetry row ops
        // (3) The matrix on the right is the inverse (was the identity matrix)
        // There are 3 elemtary row ops: (I combine b and c in my code)
        // (a) Swap 2 rows
        // (b) Multiply a row by a scalar
        // (c) Add 2 rows
    
        //if the matrix isn't square: exit (error)
        if(M.length !== M[0].length){return;}
    
        //create the identity matrix (I), and a copy (C) of the original
        var i=0, ii=0, j=0, dim=M.length, e=0, t=0;
        var I = [], C = [];
        for(i=0; i<dim; i+=1){
            // Create the row
            I[I.length]=[];
            C[C.length]=[];
            for(j=0; j<dim; j+=1){
    
                //if we're on the diagonal, put a 1 (for identity)
                if(i==j){ I[i][j] = 1; }
                else{ I[i][j] = 0; }
    
                // Also, make the copy of the original
                C[i][j] = M[i][j];
            }
        }
    
        // Perform elementary row operations
        for(i=0; i<dim; i+=1){
            // get the element e on the diagonal
            e = C[i][i];
    
            // if we have a 0 on the diagonal (we'll need to swap with a lower row)
            if(e==0){
                //look through every row below the i'th row
                for(ii=i+1; ii<dim; ii+=1){
                    //if the ii'th row has a non-0 in the i'th col
                    if(C[ii][i] != 0){
                        //it would make the diagonal have a non-0 so swap it
                        for(j=0; j<dim; j++){
                            e = C[i][j];       //temp store i'th row
                            C[i][j] = C[ii][j];//replace i'th row by ii'th
                            C[ii][j] = e;      //repace ii'th by temp
                            e = I[i][j];       //temp store i'th row
                            I[i][j] = I[ii][j];//replace i'th row by ii'th
                            I[ii][j] = e;      //repace ii'th by temp
                        }
                        //don't bother checking other rows since we've swapped
                        break;
                    }
                }
                //get the new diagonal
                e = C[i][i];
                //if it's still 0, not invertable (error)
                if(e==0){return}
            }
    
            // Scale this row down by e (so we have a 1 on the diagonal)
            for(j=0; j<dim; j++){
                C[i][j] = C[i][j]/e; //apply to original matrix
                I[i][j] = I[i][j]/e; //apply to identity
            }
    
            // Subtract this row (scaled appropriately for each row) from ALL of
            // the other rows so that there will be 0's in this column in the
            // rows above and below this one
            for(ii=0; ii<dim; ii++){
                // Only apply to other rows (we want a 1 on the diagonal)
                if(ii==i){continue;}
    
                // We want to change this element to 0
                e = C[ii][i];
    
                // Subtract (the row above(or below) scaled by e) from (the
                // current row) but start at the i'th column and assume all the
                // stuff left of diagonal is 0 (which it should be if we made this
                // algorithm correctly)
                for(j=0; j<dim; j++){
                    C[ii][j] -= e*C[i][j]; //apply to original matrix
                    I[ii][j] -= e*I[i][j]; //apply to identity
                }
            }
        }
    
        //we've done all operations, C should be the identity
        //matrix I should be the inverse:
        return I;
    }
    

    Hier geklaut: http://blog.acipo.com/matrix-inversion-in-javascript/



  • var i=0, ii=0, j=0, dim=M.length, e=0, t=0; 
         var I = [], C = [];
    

    sind Klassen oder ? die darf ich nicht verwenden



  • das hier ist die aufgabe

    soll zuerst die Dimension n eingegeben werden, dann zeilenweise die Matrix. Die
    einzelnen Spaltenelemente sollen durch ein Leerzeichen getrennt werden.
    Bevor die Rechnung beginnt, soll die Matrix auf dem Bildschirm angezeigt werden und
    der Anwender bestätigen, ob die Eingabe richtig war oder ob die Eingabe wiederholt
    werden soll.
    Jetzt wird die Matrix invertiert. Stellt sich dabei heraus, daß die Matrix singulär ist (d.h.,
    nicht invertierbar), soll das Programm nicht abstürzen, sondern eine Meldung
    ausgeben.
    Weiterhin soll ein Textfile erzeugt werden, in dem die Matrix und – so existent – die
    inverse Matrix gespeichert sind. Existiert die inverse Matrix nicht, soll es auch im
    Textfile eine Meldung geben.
    Ob Sie die Inverse über Determinanten oder über Gauss berechnen, bleibt Ihnen
    überlassen und ist gleichwertig.

    ich bekomm es nur leider nicht hin 😞



  • JJc schrieb:

    ich bekomm es nur leider nicht hin 😞

    Tja, also hier wird dir (hoffentlich) keiner deine Hausaufgaben liefern.

    JJc schrieb:

    var i=0, ii=0, j=0, dim=M.length, e=0, t=0; 
         var I = [], C = [];
    

    sind Klassen oder ? die darf ich nicht verwenden

    Naja, es ist Javascript. Man müsste es schon für C++ anpassen.



  • JJc schrieb:

    for (j = 0; j < n; j++)
                        {
                            printf("\t%g", invmatrix[i][j-n]);
                        }//for j
    

    j ist immer kleiner als n. Somit hast du einen negativen Index.
    Das kommt nicht gut.

    Benutze eigenen Funktionen.
    Für die Eingabe, Ausgabe, Berechnung, ....

    Dann brauchst du z.B die Matrixausgabe nur einmal machen und kannst sie sehr leich prüfen.
    Auch ist es übersichtlicher, wenn du die Eingabe wiederholen willst.


  • Mod

    JJc schrieb:

    Zeilen vertauschen, falls das Pivotelement eine Null ist

    z<n, 2 * n>(A, k, i);
    

    Das ist allerdings sehr weit von dem entfernt, was diese Zeile tatsächlich tut: effektiv nichts.
    z,n,k und i sind ints, A ist ein float[20][20]-Array.
    Es wird daher folgendes gemacht:
    1. z wird mit n bzgl. kleiner-als Verglichen, das Ergebnis wird verworfen
    2. die Ausdrücke A und k (die nichts weiter tun) werden ausgewertet und das Ergebnis verworfen
    3. Der Wert 2*n wird mit dem Wert i größer-als verglichen, das Ergebnis wird verworfen.
    Die Zeile verändert also weder den Zustand eines Objektes, noch wird der Wert des Ausdruckes in irgendeiner Weise verwendet.


Anmelden zum Antworten