eigener dateentyp



  • Hey,

    lies den Artikel durch: http://c-plusplus.net/forum/232010

    Thingol 🙂



  • so hier noch mal was, aber es klappt nicht

    #include <iostream>
    #include <vector>
    using namespace std;
    
    class BigNum
    {
     BigNum () { vector<unsigned long> ziffern;}
     BigNum operator+ (const vector<unsigned long>& v1, const vector<unsigned long>& v2) const
     {
       ziffern = v1;
       return ziffern += v2;
     }
    
     private:
     vector<unsigned long> ziffern;
    };
    

    Die Velermeldungen lauten:

    "grosse_zahlen.cpp": E2080 'BigNum::operator +(const vector<unsigned long,allocator<unsigned long> > &,const vector<unsigned long,allocator<unsigned long> > &) const' muß mit einem Parameter deklariert werden in Zeile 9
    "grosse_zahlen.cpp": E2285 Keine Übereinstimmung für 'vector<unsigned long,allocator<unsigned long> >::operator =(const vector<unsigned long,allocator<unsigned long> >)' gefunden in Funktion BigNum::operator +(const vector<unsigned long,allocator<unsigned long> > &,const vector<unsigned long,allocator<unsigned long> > &) const in Zeile 10
    "grosse_zahlen.cpp": E2093 'operator+=' ist im Typ 'vector<unsigned long,allocator<unsigned long> >' für Argumente desselben Typs nicht implementiert in Funktion BigNum::operator +(const vector<unsigned long,allocator<unsigned long> > &,const vector<unsigned long,allocator<unsigned long> > &) const in Zeile 11
    


  • Gucky schrieb:

    Velermeldungen

    😮

    Schau dir den Artikel über Operatorüberladung an. Dort wird erklärt, wie die Operatoren üblicherweise überladen werden.

    Übrigens: Der Rumpf deines Konstruktors enthält eine sinnlose Deklaration.



  • Okay, du willst es wirklich selber probieren, das ist ja auch in Ordnung.
    Aber wie wäre es, wenn du statt des vector<unsinged long> vielleicht erst einmal ein vector<char> nimmst. Jeder char stellt eine Ziffer dar. Es ist natürlich schon Verschwendung, da pro Ziffer normalerweise nur 4 Bit benötigt werden, aber dies ist definitiv der einfachste Weg, seine eigene BigInt-Bibiothek zu schreiben. Später, wenn die Grundprinzipien verstanden wurden, kann es entweder umgeschrieben oder auf vorgefertigte Lösungen umgestiegen werden.
    PS: Velermeldungen 😕


  • Mod

    Vicious Falcon schrieb:

    da pro Ziffer normalerweise nur 4 Bit benötigt werden,

    😮 Willst du ihm etwa ein Zehnersystem empfehlen? unsigned long ist schon fein. Eventuell auch unsigned int, weil dies der native Datentyp des System sein 'sollte'.



  • Nein*, empfehlen würde ich eine Klasse Digit, die vieles intern regelt.
    Und einen vector<Digit> / eine deque<Digit>.
    Und ja, das Dezimalsystem ist für Lernzwecke deshalb geeignet, da man das Rechnen in diesem System bereits in der Grundschule gelernt hat. Ich habe das so mal vor einiger Zeit gemacht, es läuft wunderbar, mittlerweile mit 32 Bit-Werten, die jeweils 8 Ziffern verwalten.

    Edit: hier müsste ein Ja stehen :p


  • Mod

    Und ja, das Dezimalsystem ist für Lernzwecke deshalb geeignet, da man das Rechnen in diesem System bereits in der Grundschule gelernt hat.

    😕 Aber so ist das doch komplizierter als das native Format des Computers. Beim Dezimalsystem muss man Überläufe abfragen, bei meinem Vorschlag kann man die Überlaufeigenschaften der unsigned Arithmetik benutzen.

    edit: Oder mir ist einfach nicht bewusst, wie schwer sich andere Leute tun, in anderen Zahlensystemen zu denken. 🙂



  • Ich habe es (auch) deshalb gemacht, da man wirklich große Zahlen mit einem string initialisieren (können) muss. Wie geschrieben, es ist schon eine Zeit her.

    Number n1("15615616156156187784567894864564984894564984984894988749849489489");
    Number n2("789789456156494894894894778978974894984747894841512648945612318461231894198156");
    Number n3(n1*n2);
    n3*=10232432;
    cout << n3.AsString()<<endl;
    

    führt zur Ausgabe

    126.197.085.158.388.492.014.666.574.562.203.133.663.511.929.310.329.751.922.123.
    787.558.339.601.204.496.112.549.724.891.672.688.735.968.565.347.887.471.606.416.
    213.047.981.388.928.182.870.568.634.688
    

    Es gibt viele Wege, aber selbst auf meinem Uralt-Notebook geht dies (Compiler sei natürlich Dank) ohne spürbare Wartezeit.

    Edit: Wer so etwas macht, hat (wie ich) die Notwendigkeit von so großen Zahlen völlig überschätzt 😃



  • Vicious Falcon schrieb:

    Wer so etwas macht, hat (wie ich) die Notwendigkeit von so großen Zahlen völlig überschätzt 😃

    Größenwahn quasi 😃



  • HighLigerBiMBam schrieb:

    Größenwahn quasi 😃

    ROFL 😃



  • so nochmal

    class BigNum 
    {
    	const BigNum operator+(BigNum const& lhs, BigNum const& rhs)
    	{
    		BigNum tmp(lhs); //Kopie des linken Operanden 
    		tmp += rhs; //Implementierung mittels des +=-Operators 
    		return tmp; 
    	}
    };
    

    wobei aber mein compiler sagt, dass dem operator zu viele parameter übergeben werden 😞



  • ist auch logisch, weil du innerhalb der Klasse einem Operator immer nur rhs (du hast rhs und THIS!) übergeben musst. Wenn du zwei parameter brauchst musst du die Überladung friend machen, oder besser außerhalb der Klasse deklarieren.



  • aber wieso schreiben die das dann so hier?

    Übliche Implementierung:
    C/C++ Code: 
    const X operator+(X const& lhs, X const& rhs) 
    { 
      /* Erzeugen eines neuen Objektes, dessen Attribute gezielt einzeln gesetzt werden. Oder: */ 
      X tmp(lhs); //Kopie des linken Operanden 
      tmp += rhs; //Implementierung mittels des +=-Operators 
      return tmp; 
    }
    


  • Ja außerhalb der Klasse!



  • class BigNum 
    { 
    public:
     vector<unsigned long> ziffern; 
     bool sign; 
    }; 
    
    BigNum operator+(BigNum const& lhs, BigNum const& rhs)
    {
    	BigNum tmp(lhs); //Kopie des linken Operanden 
    	tmp = rhs + lhs; //Implementierung mittels des +=-Operators 
    	return tmp; 
    }
    

    jetzt kommt es nur noch zu einem speicherüberfluss (warum weiß eich nicht) und ich kann nicht über einen konstruktor normal werte an ziffern übergeben.
    Kann mir jemand sagen wie das geht bzw. wie ich vector als schablone für meinen eigenen datentyp benutzten kann??



  • rhs + lhs das kann nicht klappen, du rfust ja den selben Operator REKURSIV auf. Du musst schon Methoden oder Werte zusammenrechnen.



  • Dann mußt Du auch += schreiben.

    BigNum operator+(BigNum const& lhs, BigNum const& rhs)
    {
    	BigNum tmp(lhs); //Kopie des linken Operanden 
    	tmp += rhs; //Implementierung mittels des +=-Operators 
    	return tmp; 
    }
    

    jetzt kommt es nur noch zu einem speicherüberfluss

    Will ich auch haben. 😋



  • Speicher im Überfluss ist immer gut :), ich frag mich aber dann nur, wie sein += Operator aussieht...



  • muss ich jetzt was in operator+ steht auch in plus schreieben???

    const X X::plus(X const& rhs) const; //Implementiert die Addition 
    const X operator+(X const& lhs, X const& rhs) 
    { 
      return lhs.plus(rhs); 
    }
    

    ich versteh nicht ganz ób jetzt bei Implementiert die Addition noch was fehlt.

    ich geh mal nicht davon aus aber wo muss ich es dann in meiner klasse unterbringen??



  • Dann kannst du auch gleich; const X operator+( X const& rhs) (in der Klasse) machen. this (lhs) hast du ja eh. Volkards implementation ist natürlich korrekt, wenn du die Implementation im += Operator durchführst! Letztlich ist es egal was du machst, denn spätestens in der Implementation musst du die Klassen irgendwie addieren. Und dies musst du deiner Klasse beibringen. Bei einfachen Datentypen kannst du dies durch eine Gettermethode machen, aber bei Vectoren musst du zeigen, wie der vector von lhs und rhs zusammenaddiert werden!? Komponentenweise, oder einfach nur in einen vector schieben? All dies obliegt dir.


Anmelden zum Antworten