Zugriff auf und Positionierung in Array



  • Hallo,
    ich muss zur Zeit ein Programm schreiben, das zwei Matrizen multipliziert, was eigentlich kein Problem ist. Nur habe ich dabei das Problem, dass die eine der beiden zu multiplizierenden Matrizen keinen "normalen" Aufbau hat. Vielmehr hat sie nur an bestimmten Stellen Werte die von 0 verschieden sind. Mir geht es nun
    darum wie ich diese Werte aus einem anderen - vorher erzeugten Array heraushole und richtig positioniere. Soviel mal als Erklärung vorab.

    Matrizenmultiplikation sieht so aus: F * u = f
    Hierbei ist F eine n x m Matrix, wobei die Spaltenzahl immer um eins größer als die Zeilenzahl n ist. Die Anzahl der Zeilen wird am Anfang des Programms abgefragt und m entsprechend initialisiert. Die Matrix u ist eine einspaltige Matrix m x 1 und f dann entsprechend ebenfalls eine einspaltige Matrix n x 1.

    Die Matrix F ist wie folgt aufgebaut:

    1        2         3        ...       n-1         n          n+1
    1   1/b1    -1/b1                
    2            1/b2        -1/b2            
    .
    .                              ...    ...        
    n-1                                         1/b(n-1)    -1/b(n-1)    
    n                                                          1/bn    -1/bn
    

    In Worten ausgedrückt:

    1. Zeile, 1. Spalte: 1/b1
    1. Zeile, 2. Spalte: -1/b1
    Alle anderen Spalten der 1. Zeile sind 0

    2. Zeile, 1. Spalte: 0
    2. Zeile, 2. Spalte: 1/b2
    2. Zeile, 3. Spalte: -1/b2
    Alle weiteren Spalten der 2. Zeile sind 0

    3. Zeile, 1. Spalte: 0
    3. Zeile, 2. Spalte: 0
    3. Zeile, 3. Spalte: 1/b3
    3. Zeile, 4. Spalte: -1/b3
    Alle weiteren Spalten der 3. Zeile sind 0

    So setzt sich das Schema bis zur letzten (n-ten) Zeile fort. Die Belegung der n-ten Zeile lautet dann:
    n-te Zeile, 1. Spalte bis n-1. Spalte: 0
    n-te Zeile, n. Spalte: 1/bn
    n-te Zeile, n+1. Spalte: -1/bn

    Zum Einlesen der Werte b1 bis bn habe ich ein Feld von Zeigern auf Zeilen programmiert das wie folgt aussieht (bz und bs sind die Zeilen- und Spaltenanzahl die vorher im Programm bestimmt wurden):

    // Eindimensionales Feld von Zeigern auf Zeilen anlegen und einlesen der Breiten b
    
            pBreite = new double*[bz];
            for (int i=0;i<bz;i++)
            {
                pBreite[i] = new double[bs];
                cout<<"Eingabe der Breite b von Scheibe "<<i+1<<": ";
                cin>>**(pBreite+i);
            }
    

    Bei der Programmierung der Matrix F war mein Gedankengang folgender:
    - wenn die Spaltennummer kleiner als die Zeilennummer ist schreibe 0 in das entsprechende Matrizenelement
    - wenn Zeilennummer und Spaltennummer gleich sind schreibe 1/b-Wert der entsprechenden Zeile in das Matrizenelement – z.B.: Zeile 2 1/b2
    - wenn die Spaltennummer um eins größer ist als die Zeilennummer schreibe –1/b-Wert der entsprechende Matrizenelement
    - wenn die Spaltennummer um 2 oder mehr größer ist als die Zeilennummer schreibe 0 in das entsprechende Element

    Fz und Fs sind die Zeilen- bzw. Spaltenzahl die ebenfalls vorher im Programm bestimmt wurden.

    // Mehrdimensionales Feld von Zeigern auf Zeilen anlegen zur Erzeugung der Matrix F und einlesen der Breiten b
    
            pMatFs = new double*[Fsz];
            for (int i=0;i<Fz;i++)
            {
                for (int j=0;j<Fs;j++)
                {
                    if (j<Fss)
                    {
                    pMat[i][j] = 0;
                    }
                    else if (j=Fs)
                    {
                        pMat[i][j] = 1/pBreite[i];
                    }
                    else if (j=Fs+1)
                    {
                        pMat[i][j] = -1/pBreite[i];
                    }
                    else if (j>Fs+1)
                    {
                        pMat[i][j] = 0
                    }
                }
            }
    

    Leider funktioniert es noch nicht so gewünscht.

    Mir stellen sich hier noch folgende Fragen:

    - wäre es sinnvoller/einfacher die Matrix b als Vektor zu definieren/programmieren vector<double> b(bz) das es sich ja in diesem Fall nur um ein eindinemsionales Feld
    - kann ich aus der Schleife der F-Matrix heraus die b-Matrix überhaubt so ansprechen? Der Gültigkeitsbereich von pBreite[] wurde ja nicht verlassen
    - Ich habe mit i und j Laufvariablen für die Zeilen und Spalten definiert – ich ahne aber das nicht der von mir gewünschte Effekt, nämlich das Ansprechen der gleichen Zeilen- bzw. Spaltennummer erreicht wird, sondern die jeweilige Anzahl der Zeilen/Spalten.

    Für Hinweise/Anregungen//Lösungs-)Vorschläge wäre ich überaus dankbar 🙂

    Marie



  • fuer ne sparsam besetzte matrix willst du dir vlt ne spezielle klasse schreiben und operator() (fuer elementzugriff) und operator* ggf ueberladen, wobei op* lieber ausserhalb liegt vlt. als zeigerfeld zu speichern ist wenig sinnig, nutze lieber das spezielle wissen ueber die matrixform aus um die elemente schlau in nem 1d feld abzugelen. du kannst dir auch boost.ublas anschauen was spezielle klassen fuer tridiagonalmatrizen vlt schon hat.



  • Benutze stl Container, mach ne Matrix klasse: Bsp:

    typedef std::vector< std::vector< double> > Matrix_t;
    
    class MyMatrix{
    
    Matrix_t m_objMatrix;
    
    MyMatrix(size_t x=1, size_t y= 1) : m_objMatrix(x, std::vector<double>(y,0.0)){
    
    }
    void Set(size_t x,size_t y,double Val){
     m_objMatrix[x][y]=Val;
    }
    double Get(size_t x,size_t y){
     return m_objMatrix[x][y];
    }
    
    };
    


  • Joar - ich würds auch mit 2 Vektoren machen - aber würds gleich als Template machen...

    Multiplikation von Matrizen ist aber schwer, weil man das *= nicht so wirklich (wie sonst immer) nutzen kann - du musst also erst mal eine Matrix erstellen, die so groß ist, wie die Zielmatrix...

    Und dann bauste einfach die beiden Schleifen, die die beiden Matrizen zeilen- und spaltenweise multiplizieren und in die neue Matrix schaufeln...

    Ich würd das zu erst so machen und dann, wenn das zu langsam geht oder zu unelegant ist, kann man immer noch ne extra Funktion bauen, die nur fürs Multiplizieren einer oberen Dreiecks-Matrix ist - oder fängst halt gleich damit an... Ich würd ja auch fast mal 3 Zeilen pseudo-code hinschreiben, aber das is mir gerad zu viel zum Nachdenken, sry ^^

    vll hats ja trotzdem was geholfen...

    bb


Anmelden zum Antworten