Matrix und Vektoren?



  • Hey .
    Habe einen allgemeinen Überblick über c++,
    doch mit mathematischen Problemstellungen ist das ja so eone Sache ..
    Wie stelle ich algemein eine Matrix und einen Vektor dar,
    und wie stelle ich es an diese zu multiplizieren?
    Array oder Pointergebrauch?oder beides?
    Danke



  • Hallo,

    ein Vektor ist in C++ ein Array, wobei Vektor, soweit ich weiß, auch ein gängiger Begriff ist:

    Statisch:

    int a[100]; // int-Array mit 100 Elementen Indices von 0 bis 99
    

    Dynamisch:

    int* a = new int[100];
    
    delete[] a;
    

    Bei der dynamischen Version hat es den Vorteil, dass du dynamische Größen einsetzen kannst, während du bei der statischen Version nur Konstante einsetzen darfst, soweit ich weiß. (manche Compiler lassen auch variable Werte zu, inwiefern der Standard das erlaubt, weiß ich nicht)

    Matrizen kannst du als zweidimensionale Arrays darstellen:

    int a[100][100];
    

    oder als lineares Array:

    int a[100*100];
    

    Wobei du bei der letzten Version folgendermaßen auf ein Feld in deiner Pseudo-Matrix zugreifen kannst:

    a[breite*y+x]
    

    MfG MAV



  • Ich denke er meint Vektoren und Matrizen aus mathematischer Sicht.
    Matrizen hab ich keine Ahnung. Vektoren kannst du entweder in der Koordinatenschreibweise darstellen (x-Achse, y-Achse) oder als paar von Richtung und Betrag (wird wahrscheinlich so gut wie nicht gemacht).
    geloescht (der sonst über Vektoren nicht mehr so viel weiß)



  • Wie würde man es denn ,,aus mathematischer Sicht'' anders machen?

    Da bietet es sich natürlich an, eine eigene Klasse zu schreiben, die entsprechende Funktionen bereitstellt.

    Ach, ich vergaß:
    Die Operatoren (+-/*) musst du für Vektoren und Matrizen selber schreiben.



  • Ich denke er meint mit Vektor nicht ein Gruppe von Elementen, also z.B. int foo[10] sondern einen Verschiebungspfeil (aus nem Matheheft: "Die unendliche Menge aller Pfeile einer Verschiebung heißt Vektor")
    geloescht



  • Den Code überall über Arrays oder gar Zeiger zu simulieren ist nicht gerade im Sinne von C++ 😉

    Willst du selber eine Klasse für Vektoren und Matrizen schreiben? Dann sind Klassen, die ein privates Array verwalten und viele Operatoren überladen das, was sich anbietet. Falls du einfach nur ein mathematisches Problem lösen willst, musst du nach fertigen Klassen im Internet suchen, weil Standard-C++ da (leider) nichts anbietet.



  • Dann mach ich mal auch noch einen Vorschlag:

    Klasse Matrix schreiben, die 2-dim Array von floats hält, sowie 2 int's
    welche die Dimensionen angeben.
    Evtl. Klasse Vektor als Ableitung von Matrix schreiben (brauchst du aber eigentlich nicht).
    Dann die Rechenfunktionen rein.
    Ich würde die Operatoren nicht unbedingt überschreiben, da man
    so nicht schön zurückgeben kann, ob die Operation überhaupt
    definiert ist.

    Jockel



  • operatoren überladen bietet sich aber geradezu an, wenn man standard operationen unterstuetzen will, um eine gefaellige schreibweisse zu erreichen ...

    oder willst du immer schreiben

    Matrix m1,m2,m3; 
    // erste version 
    m1 = m2.AddMatrix(m3);
    // wobei dann m2 auch den Add abbekommen hat .
    
    // oder 
    m1 = matrix::Add(m2,m3);
    

    ein simples
    m1 = m2 + m3;
    ist doch viel intuitiver ! Zumal es eine standard addition fuer matrizen gibt

    und dann versuch mal
    m1 = m2 +m3 + m4 + m5;
    uebersichtlich mittels Methoden oder externe funktionen zu schreiben :p

    Klasse Matrix schreiben, die 2-dim Array von floats hält, sowie 2 int's

    Naechste Ausbaustufe um die Klasse variabler allgemeiner zu machen -> template ! nur floats sind langweilig 😃

    Ciao ...



  • Prinzipel hast du ja Recht, aber blöd dabei ist ja das m1 = m2 + m3
    in 99% der Fälle nicht definiert ist. Daher meine Idee das irdendwie so

    bool Add(const Matrix& m1, const Matrix& m1, Matrix& result);

    zu machen.
    Bin mir aber auch nicht sicher, was ich besser finde.

    Jockel



  • bool Add(const Matrix& m1, const Matrix& m1, Matrix& result);

    Naja, variable parameter mag ich ned so ... und vordefinierte funktionen fuer 2-55 Parameter find ich auch ned so doll. C++ unterstuetzt halt das ueberladen von operatoren ... und ich seh nix, was wirklich entgegenspricht.

    aber blöd dabei ist ja das m1 = m2 + m3
    in 99% der Fälle nicht definiert ist.

    was meinst du damit ?

    Ich hab ned Mathe studiert ... eher was fachliches. Also schlag mich, wenn es falsch ist.

    aber ist ned matrize + matrize definiert, und wenn die dimensionen unterschiedlich sind, wird halt aufgefuellt ?

    und wenn das in einem Fall nicht der fall sein darf, was auch vorkommen kann, dann kannst die Dimensionen auch mit typisieren. Dann ist die Addition mit matrizen unterschiedlicher dimension ned moeglich.

    Ciao ...



  • @c++loopy
    Ich habe mir für das Problem jeweils eine Klasse geschrieben.
    Ist zwar nur für 3D, kann man ja aber erweitern.
    Die Opreatoren sind dann auch keine Problem, man sollte das auch alles im Buch
    "Numerical Algorithms with C" finden.

    Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const
    {
        Matrix3 kSum;
        for (int iRow = 0; iRow < 3; iRow++)
        {
            for (int iCol = 0; iCol < 3; iCol++)
            {
                kSum.m_aafEntry[iRow][iCol] = m_aafEntry[iRow][iCol] +
                    rkMatrix.m_aafEntry[iRow][iCol];
            }
        }
        return kSum;
    }
    


  • aber ist ned matrize + matrize definiert, und wenn die dimensionen unterschiedlich sind, wird halt aufgefuellt ?

    Ne, wird nix aufgefüllt, ist schlicht nicht definiert.
    Das war ja von Anfang an mein Einwand.
    Das mit

    Dimensionen auch mit typisieren

    hab ich nicht
    verstanden.

    @daishi: Wenn die Dimensionen fest sind, spricht natürlich gar nix
    mehr gegen ein Op-überschreiben.



  • Bei veränderlichen Größen der Matrizen, kann auch ein Operator benutzt werden.
    Dann muß da halt noch ne Größenprüfung implementiert werden und ein Fehlercode.

    Ich habe mir als Fehlercode folgendes einfallen lassen,ich habe mir die größte
    darstellbare Zahl (double) genommen und verwende diese als Fehlerindikator.
    Also wenn die Berechnung nicht möglich ist, lasse ich eine Objekt mit disem wert ausgeben.

    #define MAX_DOUBLE	 1.7976931348623158e+308
    
    const Matrix3 Matrix3::ERROR(MAX_DOUBLE,...);
    
    Matrix3 Matrix3::invers(Matrix3 rkMatrix)
    {
      bool chk=false;
    //code zum berechnen bei erfolg chk auf true
    
      if(!chk)
    
      return rkMatrix.ERROR;
    }
    

    Da muß halt nur auf diesen Wert geprüft werden.
    Bei normalen berechnungen tritt dieser Wert eigentlich nie auf, daher sind da
    keine Probleme zu erwarten.



  • Ich will da eigentlich auch gar nicht drüber streiten, insb. da
    meine Idee ja auch nicht gerade schön ist.

    Ich wollte nur sagen, dass ein Operator überschreiben hier nicht
    ganz unproblematisch ist.
    Wenn ich einen +-Operator anwende, dann erwarte ich halt, dass das auch
    in der Regel klappt. Bei allgemeinen Matrizen wird das in der Regel aber
    nicht klappen. Und jemand der die Klasse nicht kennt, wird wohl kaum nach
    jedem Gebrauch des +-Operator ein if(! m.Error ) oder sowas machen.

    Deshalb wollte ich das in eine extra Funktion einbauen, damit der Benutzer
    sofort sieht, dass das (wenn er nicht selber drauf achtet) in die Hose
    geht.

    Jockel



  • Also wenn operationen zwischen Matrizen unterschiedlicher groesse ned definiert sind, dann mach folgendes:

    template<class T, size_t dimx, size_t dimy>
    class matrix
    {
    public:
        matrix();
        matrix(const matrix & rx);
        virtual ~matrix();
    
    const matrix& operator+(const matrix & rx);
    private:
        T m_data[dimx][dimy]; // alternativ T m_data[dimx * dimy];
    };
    

    damit ist erreichst du:

    matrix<float,4,4> m1,m5;
    matrix<float,3,3> m2;
    matrix<float,2,2> m3(m2); // compilerfehler ... construktor ned definiert
    
    m5 = m1 + m2; // Compilerfehler, operator +(const matrix<float,3,3>& ) fuer klasse  matrix<float,4,4>  nicht definiert !
    

    Damit hast deine dimensionen typisiert, und eine 3x3 matrix von floats ist nen anderer typ als eine 4x4 matrix von floats

    du brauchst also nimmer zur laufzeit checken, ob deine dimensionen passen, sondern das macht der compiler fuer dich ...

    Nachteil, du musst nu schon beim compilieren wissen, wie gross deine dimension wird ... und du kannst Matrixen unterschiedlicher dimensionen nimmer nen gleichen typ von variablen zuweisen, also besipielweise unterschiedliche matrixen in ner gleichen liste fuehren ... dafuer muesstest nu fuer jede dimension nen adapter schreiben ...

    Ciao ...



  • Auch schön.

    Den Fragesteller scheint das ja hier eh nicht mehr zu interessieren, ich
    fand die Diskussion aber trotzdem ganz nützlich.

    Hab's mir auch nochmal überlegt und bin zu dem Schluss gekommen, das
    unsere erste Variante (normales Operatoren überladen) doch die Beste
    war. Wenn jemand so eine Klasse nutzt, dann weiss er wohl auch den
    theoretischen Hintergrund. Genauso wie man wissen muss, dass man einen
    Überlauf bei zu der Addition zu grosser Zahlen kriegt, oder was auch immer.

    Jockel


Anmelden zum Antworten