Vorstellung Fraction Klasse


  • Mod

    Badestrand schrieb:

    Ui, den unären Operator '+' kannte ich gar nicht - sollte der einfach "leer" implementiert werden?

    Er sollte den Wert der Zahl zurückgeben (also keine Referenz, wie man versucht sein könnte). Natürlich macht er nichts interessantes.

    Unäre Operatoren sind solche, die nur einen Operanden haben. Wir möchten z.B. Schreiben:

    Fraction x = ...
    x = -x; // unäres Minus
    x = +x; // unäres Plus - macht im Prinzip gar nichts, existiert der Systematik wegen
    


  • Firefighter schrieb:

    Mal eine Frage wie müsste ich denn += Operator für 2 FRaction objekte bauen?

    So evtl.:

    Fraction& operator+=(const Fraction& right)
    {
        m_numerator = m_numerator * right.m_denominator + right.m_numerator * m_denominator;
        m_denominator = m_denominator * right.m_denominator;
        return *this;
    }
    

    Edit: Das const vor der zurückgegebenen Referenz war mist.


  • Mod

    Mit Templates würde ich noch nicht anfangen - die aufgezeigten Probleme indizieren, dass hier wahrscheinlich noch Lernbedarf besteht. Während man damit einige Probleme elegant lösen kann, ergeben sich auch einige Schwierigkeiten, bei denen man ein gutes Verständnis der "einfachen" Klasse voraussetzen müsste.

    Die Problematik interner Überläufe muss man allerdings in jedem Falle betrachten, solange die Typen für Zähler und Nenner nicht beliebig große Zahlen erfassen können. Dabei gibt es wahrscheinlich keine richtig gute Lösung.
    Schlecht dürfte sein, diese Fälle als Fehler aufzufassen und etwa mit Exceptions zu reagieren. Man kann im Voraus kürzen (dann sollte die Klasse besser rational heißen) aber das ist keine sichere Lösung. Letztlich bleibt dann nur die Möglichkeit, einen genäherten Wert darzustellen - in diesem Moment ist die Klasse dann aber nicht mehr exakt, und die Argumentation hinsichtlich der Interaktion mit float&Co. kehrt sich um. Es kommen auch mehrere Möglichkeiten der Näherung in Frage, boost:rational etwa benutzt den größten darstellbaren Nenner und wählt den Zähler entsprechend. Eine andere Möglichkeit könnte im "übermäßigen" Kürzen bestehen (also Kürzen mit einer Zahl die nicht Teiler von sowohl Zähler als auch Nenner ist). Am Besten - in meinen Augen - dürfte noch sein, die dem exakten Ergebnis nächste darstellbare Zahl zu wählen: das läuft auf eine Kettenbruchentwicklung hinaus (oder vielleicht geht es auch eleganter, meine Mathekenntnisse sind ein bisschen eingerostet), ist also etwas komplexer aber nicht sehr kompliziert.



  • Firefighter schrieb:

    Weiterhin wollte ich fragen was ich alles ändern müsste oder ob es überhaupt Sinn macht wenn ich das ganze als Template machen.

    Macht absolut Sinn. Allerdings sollte für diesen Schritt die jetzige Klasse erstmal einwandfrei funktionieren.

    Badestrand schrieb:

    Ui, den unären Operator '+' kannte ich gar nicht - sollte der einfach "leer" implementiert werden?

    Nein, schliesslich muss der ja etwas zurückgeben. Eine Möglichkeit wäre folgende:

    Fraction operator +() const
    	{
    		return Fraction(+zaehler, nenner);
    	}
    

    @Firefighter
    Noch ein Tipp, binäre Non-Assignment Operatoren solltest du ausserhalb der Klasse, im Namensraum definieren. Notfalls in der Klasse als friend deklarieren, falls du auf non-public Member zugreifen möchtest. Nur mal ein Beispiel, was gegen Member-Funktionen spricht:

    Fraction(1, 3) * 1.5
    1.5 * Fraction(1, 3)
    


  • Ok danke an alle für eure Meinung, besonderen Dank an camper für seine Professionelle Einschätzung und Meinung 🙂 Werde mich wahrscheinlich bei Fragen noch öfters melden.



  • groovemaster schrieb:

    Noch ein Tipp, binäre Non-Assignment Operatoren solltest du ausserhalb der Klasse, im Namensraum definieren. Notfalls in der Klasse als friend deklarieren, falls du auf non-public Member zugreifen möchtest.

    Oder einfach über die Assignment-Operatoren:

    Fraction operator+( const Fraction& frac, const float val )
    {
        Fraction ret( frac );
        ret += val;
        return ret;
    }
    

    So bleibt die Logik in der Klasse; und Redundanz und so.



  • Fraction& Fraction::operator +=(const Fraction& rhs)
    {
        *this = *this + rhs;
        return *this;
    }
    

    Oft sieht man es aber, dass es genau andersrum gemacht wird: Der += operator definiert das Verhalten und der + operator ruft intern den += operator auf.

    Gruß
    Don06



  • Echt? Das hab ich so noch nie gesehen.. Naja, so oder so ist m.M.n. aber Hauptsache, dass "wirklich"-operierende Teil in der Klasse ist, die quasi-Wrapper können draußen bleiben.



  • Don06 schrieb:

    Fraction& Fraction::operator +=(const Fraction& rhs)
    {
        *this = *this + rhs;
        return *this;
    }
    

    Von diesem Code solltest Du absehen: da wird eine überflüssige temporäre Kopie erstellt. Andersherum wird ein Schuh draus.


  • Mod

    nt



  • Konrad Rudolph schrieb:

    Don06 schrieb:

    Fraction& Fraction::operator +=(const Fraction& rhs)
    {
        *this = *this + rhs;
        return *this;
    }
    

    Von diesem Code solltest Du absehen: da wird eine überflüssige temporäre Kopie erstellt. Andersherum wird ein Schuh draus.

    Hab ich nicht darauf hingewiesen, dass es oft andersrum gemacht wird?



  • Don06 schrieb:

    Konrad Rudolph schrieb:

    Don06 schrieb:

    Fraction& Fraction::operator +=(const Fraction& rhs)
    {
        *this = *this + rhs;
        return *this;
    }
    

    Von diesem Code solltest Du absehen: da wird eine überflüssige temporäre Kopie erstellt. Andersherum wird ein Schuh draus.

    Hab ich nicht darauf hingewiesen, dass es oft andersrum gemacht wird?

    Ja, aber wieso überhaupt diesen irreführenden Code zeigen? Badestrand zumindest hast Du auch erfolgreich verwirrt (oder bezog sich das auf was anderes?).



  • Konrad Rudolph schrieb:

    Badestrand zumindest hast Du auch erfolgreich verwirrt (oder bezog sich das auf was anderes?).

    Jau, ich hatte den Satz darunter irgendwie falsch gedeutet 🙂 Don, du hast anderen Code gezeigt und dann was von "andersrum" gesagt, das war einfach zu viel für mich 😃


Anmelden zum Antworten