Vektorrechner



  • Nathan schrieb:

    Hattet ihr Copy-Konstruktor/Zuweisungsoperator schon?
    Vermutlich nicht, da ihr keine Operatorüberladung kennt.
    Weil das ist die einzige Schwachstelle im Code, der Absturz bei Copy (genaugenommen beim Zerstören).
    Oh, ich sehe gerade, dass du keinen Destruktor hast. Hattet ihr den schon?
    Dürft ihr dafür std::vector verwenden, dann hast du diese Probleme nicht?

    Probleme? Erstmal schauen, ob es so auch geht.



  • Ja, ich hatte das nur überflogen.
    Er soltle natürlich erst die Fehler ausbügeln und dafür evtl. das Design ändern.



  • Zum Laufen bekomme ich es leider nicht. Meine Bitte um Verbesserungsvorschläge war wahrscheinlich die falsche Wortwahl.

    Also ich kommentiere jetzt die Zeilen die grotesk erscheinen.

    #include <iostream>
    #include <cmath>
    
    class Vektor{ 
    private: 
        double* komponenten; 
        int anzahl; 
    public: 
        Vektor(int anz=3) 
        { 
            anzahl=anz; 
            komponenten=new int[anzahl]; //Das hier ist der Ansatz den mir Volkard vorgeschlagen hat, leider wird als Warnung angezeigt: "Assigning do 'double *' from incompatible type 'int *'"  
            for(int i=0;i<anzahl;++i) 
                komponenten[i]=0; 
        } 
    
        Vektor addiere(Vektor const& b) 
        { 
            Vektor c(anzahl); 
            for(int i=0;i<anzahl;++i) 
                c.komponenten[i]=komponenten[i]+b.komponenten[i]; 
            return c; 
        } 
    
        Vektor subtrahiere(Vektor const& b) 
        { 
            Vektor c(anzahl); 
            for(int i=0;i<anzahl;++i) 
                c.komponenten[i]=komponenten[i]-b.komponenten[i]; 
            return c; 
        } 
    
        Vektor skalarprod(Vektor const& b)
        {
            double erg=0;
    
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i) 
                erg += komponenten[i]*b.komponenten[i];
    
            return erg;
        }
    
        double norm() 
        { 
            double buf = skalarprod(*this); // "No viable conversion from 'Vektor' to 'double' / benötige ich hier einen zusätlichen header?
            double erg = sqrt(buf); 
            return erg; 
        }
    
        Vektor normiere(Vektor const& b)
        {
            double buf = norm();
    
            Vektor c(anzahl); 
            for(int i=0;i<anzahl;++i) 
                c.komponenten[i]=b.komponenten[i] / buf; 
            return c; 
    
        }
    
        Vektor daten_eingeben()
        {
            for (int i=0; i<anzahl; i++) { 
                std::cout <<"Vektorkomponente eingeben: "; 
                sin >> c.komponenten[i]; // Hier hapert es leider auch an der Umsetzung, aber die Eingabe von Daten in einer Funktion durchblicke ich nicht ganz
            } 
    
        }
    
        void ausgabe()
        {
            for (int i=0; i<anzahl; ++i) {
            printf("[%f\n]", komponenten[i]);
            }
    
        }
    
    };
    
    int main() { 
        std::cout << "C++ Beispiel Vektoren:" << std::endl; 
    
        // Zwei Vektoren deklarieren 
        Vektor v1(4), v2(4); 
    
        // Daten vom Benutzer einlesen 
        v1.daten_eingeben(); 
        v2.daten_eingeben(); 
    
        // Testen der Addition und Subtraktion 
        Vektor v3 = v1.addiere(v2); 
        Vektor v4 = v1.subtrahiere(v2); 
    
        // Ausgabe der Ergebnisse ueber die Funktion ausgabe 
        v3.ausgabe(); 
        v4.ausgabe(); 
    
        // Testen des Skalarprodukts und der Normierung 
        double skalarprodukt = v1.skalarprod(v2); 
        Vektor v5 = v4.normiere(); 
    
        // Ausgabe 
        std::cout << "Skalarprodukt = " << skalarprodukt << std::endl; 
        v5.ausgabe(); 
    
        // Testen der Ueberladenen Operatoren 
        v5 = v3 + v4; 
        v5.ausgabe(); 
        v5 = v5 - v3; 
        v5.ausgabe(); 
    
        return 0; 
    
    }
    

    Könnt ihr mir Tipps geben wie ich so langsam ans Ziel gelange?

    @Nathan
    Ja, wir dürfen alles verwenden. Das Problem ist, dass wir auf uns allein gestellt sind und uns leider nichts vorgekaut wurde.


  • Mod

    Vektor(int anz=3)
    

    sollte explicit sein:

    explicit Vektor(int anz=3)
    

    dann funktioniert das return in

    Vektor skalarprod(Vektor const& b)
        {
            double erg=0;
    
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i) 
                erg += komponenten[i]*b.komponenten[i];
    
            return erg;
        }
    

    nicht mehr, weil der Rückgabetyp auch tatsächlich Unfug ist. Wird das korrigiert, gibt es auch kein Problem mit norm mehr.

    double* komponenten;
    ...
            komponenten=new int[anzahl];
    

    deklarierter Typ und der Typ von new passen nicht recht zusammen.


  • Mod

    Fällt dir nichts auf, wenn du die Zeilen 6 und 12 anguckst?

    Zeile 34: Was ist denn das Ergebnis eines Skalarprodukts für eine Art von mathematischen Objekt?

    Zeile 67: Was soll das sin sein? Woher soll es kommen? Der Compiler weiß es nicht, er kann auch nicht in deinen (oder volkards) Kopf gucken, was gemeint ist. Du musst ihm alles genau erklären.



  • Danke 🙂 new int habe ich gegen new double ausgetauscht.

    Aber beim Skalarprodukt weiß ich noch nicht ganz was ihr meint, denn ich summiere ja die Produkte der einzelnen Vektorkomponenten und das ist ja ein double -Wert oder täusche ich mich?

    Für daten_eingabe habe ich jetzt:

    Vektor daten_eingeben()
        {
            Vektor c(anzahl);
            for (int i=0; i<anzahl; i++) { 
                std::cout <<"Vektorkomponente eingeben: "; 
                std::cin >> c.komponenten[i];         } 
    
        }
    

    Ist das so besser?


  • Mod

    cpluskowski schrieb:

    Aber beim Skalarprodukt weiß ich noch nicht ganz was ihr meint, denn ich summiere ja die Produkte der einzelnen Vektorkomponenten und das ist ja ein double -Wert oder täusche ich mich?

    Das beschreibst du richtig. Aber dein Programm passt nicht zu der Beschreibung.

    Für daten_eingabe habe ich jetzt:

    Vektor daten_eingeben()
        {
            Vektor c(anzahl);
            for (int i=0; i<anzahl; i++) { 
                std::cout <<"Vektorkomponente eingeben: "; 
                std::cin >> c.komponenten[i];         } 
            
        }
    

    Ist das so besser?

    Was passiert denn mit c in Zeile 8?



  • Achsooo ok

    double skalarprod(Vektor const& b)
        {
            double erg=0;
    
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i) 
                erg += komponenten[i]*b.komponenten[i];
    
            return erg;
        }
    

    das müsste jetzt besser sein oder?

    Bei der Dateneingabe meinst du wahrscheinlich den return-Wert

    Vektor daten_eingeben()
        {
            Vektor c(anzahl);
            for (int i=0; i<anzahl; i++) { 
                std::cout <<"Vektorkomponente eingeben: "; 
                std::cin >> c.komponenten[i];         } 
    
            return c;
        }
    

  • Mod

    cpluskowski schrieb:

    Achsooo ok

    double skalarprod(Vektor const& b)
        {
            double erg=0;
            
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i) 
                erg += komponenten[i]*b.komponenten[i];
            
            return erg;
        }
    

    das müsste jetzt besser sein oder?

    Ja.

    Bei der Dateneingabe meinst du wahrscheinlich den return-Wert

    Vektor daten_eingeben()
        {
            Vektor c(anzahl);
            for (int i=0; i<anzahl; i++) { 
                std::cout <<"Vektorkomponente eingeben: "; 
                std::cin >> c.komponenten[i];         } 
            
            return c;
        }
    

    Hmm, nein. Eher nicht. Hier scheint Grundverständnis zu fehlen, was Klassen, Objekte, Member(funktionen) und Funktionen sind, wie sie sich zueinander verhalten und zusammenarbeiten. Jedenfalls wirfst du hier so vieles durcheinander, dass ich nicht mehr sagen kann, was du hier überhaupt erreichen möchtest. Mach dich erst einmal schlau über die genannten Begriffe, dann atme tief durch und mach dir langsam und gründlich Gedanken, was du hast, was du erreichen möchtest, welches der genannten Mittel dazu geeignet ist* und dann setz dies in Code um.

    *: Die Antwort darauf muss nicht unbedingt eindeutig sein. Es mag zwar Vorteile für die eine oder andere Methode geben, aber es gibt immer viele Wege zum Ziel. Aber du versuchst gerade alle Wege gleichzeitig zu gehen und kommst damit nirgendwo an. tolle Metapher 🕶 .



  • void daten_eingeben()
        {
            for (int i=0; i<anzahl; i++) { //Durchläuft alle Vektorkomponenten
                std::cout <<"Vektorkomponente eingeben: "; 
                std::cin >> komponenten[i];         } //Eingabe der jeweiligen Vektorkomponente 
    
        }
    
    // Daten vom Benutzer einlesen 
        v1.daten_eingeben(); 
        v2.daten_eingeben();
    

    Die Vektorkomponenten von v1 und v2 werden so mit Hilfe der Funktion eingegeben denke ich 😕



  • Jetzt werden sie eingegeben.



  • Ok jetzt sieht das Programm wie folgt aus:

    #include <iostream>
    #include <cmath>
    
    class Vektor{ 
    private: 
        double* komponenten; 
        int anzahl; 
    public: 
        explicit Vektor(int anz=3) 
        { 
            anzahl=anz; 
            komponenten=new double[anzahl];   
            for(int i=0;i<anzahl;++i) 
                komponenten[i]=0; 
        } 
    
        Vektor addiere(Vektor const& b) 
        { 
            Vektor c(anzahl); 
            for(int i=0;i<anzahl;++i) 
                c.komponenten[i]=komponenten[i]+b.komponenten[i]; 
            return c; 
        } 
    
        Vektor subtrahiere(Vektor const& b) 
        { 
            Vektor c(anzahl); 
            for(int i=0;i<anzahl;++i) 
                c.komponenten[i]=komponenten[i]-b.komponenten[i]; 
            return c; 
        } 
    
       double skalarprod(Vektor const& b)
        {
            double erg=0;
    
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i) 
                erg += komponenten[i]*b.komponenten[i];
    
            return erg;
        }
    
        double norm() 
        { 
            double buf = skalarprod(*this); 
    
            double erg = sqrt(buf); 
            return erg; 
        }
    
        Vektor normiere()
        {
            double buf = norm();
    
            Vektor c(anzahl); 
            for(int i=0;i<anzahl;++i) 
                c.komponenten[i]=komponenten[i] / buf; 
            return c; 
    
        }
    
        void daten_eingeben()
        {
            for (int i=0; i<anzahl; i++) { 
                std::cout <<"Vektorkomponente eingeben: "; 
                std::cin >> komponenten[i];         } 
    
        }
    
        void ausgabe()
        {
            for (int i=0; i<anzahl; ++i) {
            std::cout <<"%f\n"<< komponenten[i];
    
            }
    
        }
    
    };
    
    int main() { 
        std::cout << "C++ Beispiel Vektoren:" << std::endl; 
    
        // Zwei Vektoren deklarieren 
        Vektor v1(4), v2(4); 
    
        // Daten vom Benutzer einlesen 
        v1.daten_eingeben(); 
        v2.daten_eingeben(); 
    
        // Testen der Addition und Subtraktion 
        Vektor v3 = v1.addiere(v2); 
        Vektor v4 = v1.subtrahiere(v2); 
    
        // Ausgabe der Ergebnisse ueber die Funktion ausgabe 
        v3.ausgabe(); 
        v4.ausgabe(); 
    
        // Testen des Skalarprodukts und der Normierung 
        double skalarprodukt = v1.skalarprod(v2); 
        Vektor v5 = v4.normiere(); 
    
        // Ausgabe 
        std::cout << "Skalarprodukt = " << skalarprodukt << std::endl; 
        v5.ausgabe(); 
    
        // Testen der Ueberladenen Operatoren 
        v5 = v3 + v4; 
        v5.ausgabe(); 
        v5 = v5 - v3; 
        v5.ausgabe(); 
    
        return 0; 
    
    }
    

    Jetzt macht mich der Compiler "nur" noch auf Zeilen 110 und 112 aufmerksam. Benötige ich für diese Berechnung eine weitere Funktion?


  • Mod

    cpluskowski schrieb:

    Jetzt macht mich der Compiler "nur" noch auf Zeilen 110 und 112 aufmerksam. Benötige ich für diese Berechnung eine weitere Funktion?

    Ja. Woher soll der Compiler wissen, dass "addiere" eine Addition sein soll? Der kann kein Deutsch. Nenn die Funktion operator+ , das versteht er. Wie das mit Minus geht, darfst du dir selber erschließen.

    edit: Dann kannst du natürlich nicht mehr addiere und subtrahiere direkt wie in Zeile 94 und 95 aufrufen (beziehungsweise nur unter dem neuen Namen). Du kannst natürlich auch neue Funktionen mit dem passenden Namen schreiben, die dann die anderen Funktionen mit der gleichen Funktionalität aufrufen.



  • Natürlich wird der operator+ zusätzlich zur Methode addiere angeboten.

    Es soll ja die vorgegebene main()-Funktion unverändert laufen.

    Elegant wäre es, wenn der operator+ die Methode addiere benutzen würde oder umgegehrt, damit der eigentliche Rechencode nur einmal geschrieben werden muss.



  • Danke für die tolle Hilfe!

    Ich bin so weit, dass ich das ganze kompilieren kann 🙂

    Das ganze sieht jetzt so aus:

    #include <iostream>
    #include <cmath>
    
    class Vektor{
    private:
        double* komponenten;
        int anzahl;
    public:
        explicit Vektor(int anz=3)
        {
            anzahl=anz;
            komponenten=new double[anzahl];
            for(int i=0;i<anzahl;++i)
                komponenten[i]=0;
        }
    
        Vektor addiere(Vektor const& b)
        {
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i)
                c.komponenten[i]=komponenten[i]+b.komponenten[i];
            return c;
        }
    
        Vektor subtrahiere(Vektor const& b)
        {
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i)
                c.komponenten[i]=komponenten[i]-b.komponenten[i];
            return c;
        }
    
       double skalarprod(Vektor const& b)
        {
            double erg=0;
    
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i)
                erg += komponenten[i]*b.komponenten[i];
    
            return erg;
        }
    
        double norm()
        {
            double buf = skalarprod(*this);
    
            double erg = sqrt(buf);
            return erg;
        }
    
        Vektor normiere()
        {
            double buf = norm();
    
            Vektor c(anzahl);
            for(int i=0;i<anzahl;++i)
                c.komponenten[i]=komponenten[i] / buf;
            return c;
    
        }
    
        void daten_eingeben()
        {
            for (int i=0; i<anzahl; i++) {
                std::cout <<"Vektorkomponente eingeben: ";
                std::cin >> komponenten[i];         }
    
        }
    
        void ausgabe()
        {
            std::cout<<"[";
            for (int i=0; i<anzahl; ++i) {
                std::cout << komponenten[i]<<","<<" ";
    
            }
            std::cout<<"]";
            std::cout<<"\n";
    
        }
    
        Vektor operator+(const Vektor& b){
    
            return addiere(b);
    
        }
    
        Vektor operator-(const Vektor& b){
    
            return subtrahiere(b);
    
        }
    
    };
    
    int main() {
        std::cout << "C++ Beispiel Vektoren:" << std::endl;
    
        // Zwei Vektoren deklarieren
        Vektor v1(4), v2(4);
    
        // Daten vom Benutzer einlesen
        v1.daten_eingeben();
        v2.daten_eingeben();
    
        // Testen der Addition und Subtraktion
        Vektor v3 = v1.addiere(v2);
        Vektor v4 = v1.subtrahiere(v2);
    
        // Ausgabe der Ergebnisse ueber die Funktion ausgabe
        v3.ausgabe();
        v4.ausgabe();
    
        // Testen des Skalarprodukts und der Normierung
        double skalarprodukt = v1.skalarprod(v2);
        Vektor v5 = v4.normiere();
    
        // Ausgabe
        std::cout << "Skalarprodukt = " << skalarprodukt << std::endl;
        v5.ausgabe();
    
        // Testen der Ueberladenen Operatoren
        v5 = v3 + v4;
        v5.ausgabe();
        v5 = v5 - v3;
        v5.ausgabe();
    
        return 0;
    
    }
    

    Wenn ich für den ersten Vektor (1,1,1,1) und für den zweiten Vektor (2,2,2,2) eingebe, wird das hier ausgegeben:

    [3, 3, 3, 3, ]
    [-1, -1, -1, -1, ]
    Skalarprodukt = 8
    [-0.5, -0.5, -0.5, -0.5, ]
    [2, 2, 2, 2, ]
    [-1, -1, -1, -1, ]
    

    Ist das Prinzip und das Ergebnis der Überladung richtig?



  • Ja, geht so.

    Und dann lies Dir nochmal alles durch und schau, ob Du auch jede Zeile verstehst.
    Da gibt es nämlich noch Zeilen, die ein wenig schizo wirken. Anderen Plan angefangen und dann umgeschwenkt oder so.

    Beispiel, für was ich meine:
    In http://www.c-plusplus.net/forum/312821-11 habe ich noch ein

    unsigned int j;
    

    im Code stehen. Wenn mich einer fragen würde, warum, müßte ich doch glatt gestehen, daß die Zeile da vollkommen unsinnig ist.

    Das fällt einem dann auf, wenn man nochmal aufmerksam alles liest und sich für jede Zeile überlegt, warum sie da sein muss, was ich Dir hiermit nahelege.



  • double skalarprod(Vektor const& b)
        {
            double erg=0;
    
            Vektor c(anzahl); // Und was macht c hier? :)
            for(int i=0;i<anzahl;++i)
                erg += komponenten[i]*b.komponenten[i];
    
            return erg;
        }
    


  • Wenn ich für alle Vektorkomponenten die gleiche Zahl eingebe, wird für die Normierung [ -nan -nan -nan -nan] ausgegeben 😮

    Wie kann das sein?


  • Mod

    Diese gleiche Zahl ist zufällig 0 ?



  • Achso ich sehe gerade, dass die Vektoren der Subtraktion verwendet werden. Folglich kommt da null raus für alle Komponenten.

    Da er dann 0 durch 0 teilt kommt das dann zu Stande. Sollte man das ändern oder so lassen?


Anmelden zum Antworten