C# Matrix-Rechnungen mit C#

Nuuub

Lt. Junior Grade
Registriert
Aug. 2004
Beiträge
287
Hey ho,

bin gerade dabei ein bisschen Mathe mit C# zu betreiben (und wehe jetzt sagt hier einer, dass das Schwachsinn wäre, das weiß ich selbst ^^). Aber zurück zum Eigentlichen:
Ich versuche ne Matrix-Vektormultiplikation durchzuführen. Interne Funktionen wie Matrix.Multiply gehen leider nicht, da Visual Studio den Matrix.Namespace nicht kennenlernen möchte.
Daher hab ich das ganze von Hand versucht, allerdibngs das Problem, dass ich nicht richtig mit den Dimensionen klar komme:

Code:
public static double[] MatrixVectorMultiply(double[][] A, double[] b)
        {
            var d = new double[b.Length];
            for (var i = 0; i < A[0].Length; i++)
            {
                for (var j = 0; j < b.Length ; j++)
                {
                    d[i] += A[i][j]*b[j];
                }
            }
            return d;
        }

Das Problem liegt vermutlich bei dem A[0].Length, da die zweite Dimension genau so "groß" ist, wie die einzige von b, werden Elemente nicht mitberechnet.
Beispiel war eine 4x3 Matrix und ein 3x1 Vektor, sollte einen 4x1 Vektor ergeben, die ersten Komponenten stimmen (lt. Matlab), allerdings fehlt der vierte Eintrag komplett.
Kann man irgendwie gleich die Größe von der "Matrix" (also des double[][]-Arrays A) abfragen (hier dann [4,3]) oder wie greift man gezielt auf die jeweilige Dimension zu?
À la A(:,1) wie in Matlab?

MfG
 
---
 
Zuletzt bearbeitet:
wir haben in c(++) gelernt, dass es nicht gut ist eine matrix durch ein mehrdimensionales array darzustellen
wir haben dazu ein normales array genommen
dazu haben wir ne template class genommen - weil man will ja nicht nur double drin haben und nicht jedes mal neuschreiben müssen
Code:
template <class T>
class Matrix {
public:  
  Matrix(int n, int m) {
        zl=n;
        sp=m;

        a=new T[n*m];
        for(int i = 0; i<(n*m); i++) {
            a[i]=0;
        }

        printf("Konstruktor\n");
    }

    ~Matrix() {
        delete[] a;
        printf("\nDestruktor");
    }

    void set(int z, int s, T d) {
        a[z*sp+s]=d;
    }

    T get(int z, int s) {
        return a[z*sp+s];
    }
    int zeilen() const {
        return zl;
    }

    int spalten() const {
        return sp;
    }
private:
    Matrix();

    T* a;
    int zl, sp;
    int cnt;

als beispiel ( ist nicht vollständig - verschiedene operatoren fehlen, noch copy constructor, usw. )
dann hast du die dimensionen schon vereinfacht und das ganze soll viel perfomanter laufen laut unserem prof

dann kannst du direkt auf die anzahl der zeilen bzw spalten zugreifen
allerdings weiß ich nicht wie weit du bist und ob sich das lohnt nochmal zu schreiben
 
System.Drawing.dll eingebunden? Dann klappts auch mit der System.Drawing.Drawing2D.Matrix-Klasse.
 
Ja, die war eingebunden, nur die Multiply-Methoden da wollen nicht und die VisualStudio Hilfe is ja auch mehr schlecht als recht...
Werd mir dann wohl morgen auch nen eigenen Matrixtyp zusammenbasteln, damit man wenigstens ein bisschen + und - rechnen kann...
 
A.Length / b.Length statt A[0].Length müsste dein Problem lösen.

Sneazel schrieb:
wir haben in c(++) gelernt, dass es nicht gut ist eine matrix durch ein mehrdimensionales array darzustellen wir haben dazu ein normales array genommen
Im Speicher passiert genau dasselbe, es ist eigentlich nur eine andere Schreibweise. Von daher würde ich es nicht besser oder schlechter nennen.
Ergänzung ()

wobei:

Ein bisschen komisch ist das mit dem A[0].Length schon, bei mir compiliert das gar nicht erst.
 
Du durchläufst nicht deine gesamte Matrix, es werden alle Einträge des Vektors nur mit der ersten Zeile der Matrix multipliziert. Daher brauchst du eine zusätzliche innere Schleife um alle Dimensionen abzulaufen.

Außerdem musst du prüfen ob die Anzahl der Spalten deiner Matrix mit der Anzahl der Zeilen des Vektors übereinstimmt. Ansonsten kann man das Produkt nicht bilden.

So kannst du durch die gesamte Matrix iterieren:

Code:
.......... 


for(var i = 0; i < A.Length; i++){

    for (var x = 0; x < A[i].Length; x++){
      
           ........
    }
}

So müsste es gehen.
 
OK ich bin kein C# Profi, aber folgendes funktioniert bei mir:

Code:
namespace MatrixSharp
{
    class Program
    {
        static void Main(string[] args)
        {

            double[,] m = { { 1, 0 ,0 }, { 0, 1, 0 }, { 0, 0, 1 } }; // Einheitsmatrix, gibt den Vektor aus
            double[] x = { 1, 2, 3 }; // Testvektor
            double[] r;

            r = MatrixVectorMultiply(m, x);
        }

        public static double[] MatrixVectorMultiply(double[,] A, double[] b)
        {
            var d = new double[b.Length];
            for (var i = 0; i < A.Length/b.Length; i++)
            {
                for (var j = 0; j < b.Length; j++)
                {
                    d[i] += A[i,j] * b[j];
                }
            }
            return d;
        }
    }
}
 
@F_GXdx

Also ich kenne mich mit der C# Syntax gar nicht aus, was genau heißt denn das "A.Length/b.Length" ?
 
A.Length ist die Größe der Matrix, also in meinem Beispiel mit der E3: 3x3 = 9.

Das Problem des TEs ist, dass er die zweite Dimension der Matrix braucht. Diese kann er immer ausrechnen, indem er durch die Länge des Vektors teilt, dann kommt nämlich genau die zweite Dimension wieder heraus.

Denn es gilt immer m x n / m = n
 
Zuletzt bearbeitet:
Achso ok, das stimmt natürlich. Das kannte ich so noch nicht. Ich dachte das "/" eine andere Bedeutung als Division hat. Wie gesagt ich kenne mich mit C# nicht aus.

Aber muss er nicht dennoch prüfen ob die Zeilenanzahl des Vektors mit der Spaltenanzahl der Matrix übereinstimmt?

Ein Vektor ist ja eine n x 1 Matrix. Also muss die zweite Matrix eine k x n Matrix sein, oder nicht? Ansonsten funktioniert die Multiplikation doch nicht?
 
Moin,

da ich ja weiss was ich berechne, ist schon sichergestellt, dass Matrix und Vektor passend dimensioniert sind. Der Tip mit A.length/b.length ist gut, hatte erwartet, dass ich da die Dimensionen einzeln bekomme, aber das löst das Problem.

Besten Dank :)
 
Sorry, ich hab mein Posting gestern Abend noch mal editiert und es damit "entwertet" :freak:

A.length/b.length ist die Zeilenanzahl, also die "erste Dimension" wenn man so will. Wobei ich nicht ganz sicher bin, ob man es so sagen sollte. Sagen wir lieber Zeilenanzahl.
 
Die Signaturen sind ja auch unterschiedlich. Bei Nuub war es double[][] A.
Damit sollte ein A.Length statt A[0].Length in der äußeren Schleife passen den Fehler auch beheben.
 
Wenn es mittlerweile läuft, ist es ja gut, aber ergibt in dem Code ganz oben nicht Folgendes ein Problem?

Code:
var d = new double[b.Length]

bei einer 4x3 mal 3x1 Multiplikation kommt schließlich eine 4x1 Matrix raus, b.length ist aber doch 3. Der Rest vom Code müsste dann schon passen.
Dann müsste doch dort auch A[0].Length klappen?
 
Zurück
Oben