Klassen in C++ Durchschnitt von zwei Zahlen berechnen


  • Mod

    Und ABIs interessieren bei Designfragen inwiefern? Typischer Beitrag von dir, völlig nutzlos, nur um irgendwas vermeintlich klug klingendes zu sagen.



  • @SeppJ sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    Und ABIs interessieren bei Designfragen inwiefern?

    Kommt drauf an ob man ne lib oder ne Anwendung macht.


  • Mod

    @Tyrdal sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    @SeppJ sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    Und ABIs interessieren bei Designfragen inwiefern?

    Kommt drauf an ob man ne lib oder ne Anwendung macht.

    Was soll das ändern an der Designfrage, was Teil einer öffentlichen Schnittstelle sein sollte und was nicht? Nichts. Du darfst intern deine Klasse gerne PIMPLn, wenn dich stört, dass man abhängige Dinge neu compilieren muss, wenn man irgendwo etwas ändert. Eine Designfrage ist, wie man vermeidet, dass man abhängige Dinge neu programmieren muss, wenn man irgendwo etwas ändert.



  • @SeppJ sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    Und ABIs interessieren bei Designfragen inwiefern? Typischer Beitrag von dir, völlig nutzlos, nur um irgendwas vermeintlich klug klingendes zu sagen.

    Das ist wieder eine typische Antwort von Dir, 90% verstanden und an den restlichen 10% scheiterst Du kläglich.

    Die ABI Änderungen, die sich durch Codeänderungen ergeben, erzwingen z.B. für Libraries ein anderes Design. Du willst mir doch nicht ernsthaft erzählen wollen, dass bei Qt o.ä. man bei einem Minor Release die ABI zerbrechen kann, und die Kunden das toll finden? Dieser Umstand ist Design relevant und das sollte ein jeder wissen und anwenden können.


  • Mod

    @john-0 sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    @SeppJ sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    Und ABIs interessieren bei Designfragen inwiefern? Typischer Beitrag von dir, völlig nutzlos, nur um irgendwas vermeintlich klug klingendes zu sagen.

    Das ist wieder eine typische Antwort von Dir, 90% verstanden und an den restlichen 10% scheiterst Du kläglich.

    Die ABI Änderungen, die sich durch Codeänderungen ergeben, erzwingen z.B. für Libraries ein anderes Design. Du willst mir doch nicht ernsthaft erzählen wollen, dass bei Qt o.ä. man bei einem Minor Release die ABI zerbrechen kann, und die Kunden das toll finden? Dieser Umstand ist Design relevant und das sollte ein jeder wissen und anwenden können.

    Es geht nicht darum, ob das falsch oder richtig ist, sondern dass das absolut gar nichts mit dem Thema zu tun hat. Du kommst in jeden Thread rein, konstruierst einen Strohmann, der so weit weg geholt ist, dass ganze Astrobiologielehrstühle sich nur damit beschäftigen, und greifst diesen dann an, um dich irgendwie toll zu fühlen, weil du eine Diskussion gewinnst, die aber nur in deinem eigenen Kopf existiert. Sieht man auch wieder toll an deiner Antwort hier, die überhaupt nicht auf irgendetwas eingeht, sondern mir irgendetwas zu Qt in den Mund legen möchte, das du dir wieder zwecks Selbstdarstellung ausgedacht hast. Hat schon seinen Grund, warum so viele der längerfristigen Mitglieder dieses Forums dich auf ihrer Ignoreliste haben. Aber uns Moderatoren nervt es halt einfach nur, und du hilfst halt auch niemandem damit, was eigentlich der Hauptzweck dieses Forums ist. Wahrscheinlich denkst du sogar wirklich, dass andere irgendwie beeindruckt wären von deiner scharfsinnigen Logik und schlagenden Argumenten, wenn sie nichts mehr erwidern, obwohl sie bloß genervt die Augen verdrehen und die durchsichtige Strohmanndiskussion ignorieren.



  • @SeppJ sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    sondern dass das absolut gar nichts mit dem Thema zu tun hat.

    Es geht um das Thema: Wie beeinflusst protected das Design von Klassen in C++. Das Design von C++ Klassen wird eben nicht nur von der API sondern auch von der ABI beeinflusst. Das könnte man nun akzeptieren, und als Ergänzung zu dem schon Geschriebenem akzeptieren. Dir fällt nichts besser ein zu wiederholten Mal eine Metadiskussion zu starten. Weshalb fällt es dir so schwer persönliche Angriffe zu unterlassen?


  • Mod

    @SeppJ hat Recht: Durch protected erschafft man eine Abhaengigkeit zum (protected) Interface. Abhaengigkeiten zu Implementierungsdetails sind aber die #1 Motivation dafuer, ueberhaupt private zu haben. Deshalb ergibt protected i.d.R. nur bei Hilfsmembern Sinn.

    @john-0 Wie viele Leute muessen Dir Deine perniziösen Verhaltensmuster noch psychoanalysieren, bevor Du mal anfaengst zu reflektieren? Unabhaengig davon, ob irgendwelche nuetzlichen Erkenntnisse in Deinen Posts enthalten sind: Jeder Thread mit Dir artet in eine passiv-aggressive Spirale von irrelevanten Seitenthemen aus, ohne am Ende noch Mehrwert zu bieten. Frag Dich mal, ob das Resultat mit Deinen (hoffentlich aufrichtigen) Intentionen übereinstimmt.



  • @Columbo

    Es wird sich hier im Forum immer wieder geäußert, dass so wenige Nutzer sich länger im Forum engagieren. Dreimal darfst du raten, weshalb das der Fall ist. Glaubst du ernsthaft normale Menschen haben Lust auf diese fortgesetzte verbalen Entgleisungen(1) der Mods in diesem Forum?

    (1) Dir fällt auch nichts besseres ein als im erstes Posting mir gleich ein krankhaftes Verhalten anzudichten.

    Ich kenne so ein Verhalten nur aus dem Usenet, von einer bestimmten Person mit Kürzel Fefe. Aber Fefe war für sachliche Argumente zugänglich.

    P.S. Wenn du mich nicht im Forum haben willst, schreib das einfach, anstatt mich jedesmal anzupöbeln.



  • @john-0 sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    länger im Forum engagieren...Glaubst du ernsthaft normale Menschen haben Lust auf diese fortgesetzte verbalen Entgleisungen(1) der Mods in diesem Forum?

    Ich bin seit 2009 registriert und war davor schon ein paar Jahre nicht registriert unterwegs (ging damals noch). Ich kann mich an keine nenneswerte Entgleisung eines Mods erinnern.

    @john-0 sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    Wenn du mich nicht im Forum haben willst, schreib das einfach, anstatt mich jedesmal anzupöbeln.

    Wenn dich jemand nicht im Forum haben wollte, dann hätte sich @SeppJ wohl nicht extra die Mühe gemacht, mal zu schreiben, warum deine Antworten soooo anstrengend sind.



  • Was bin ich froh dass ich nur die Schatten dieser Diskussion sehe 🙂



  • Mich juckt das auch nicht. Habe zwar niemanden ignoriert, aber ich finde es gut, wenn es auch solche Diskussionen gibt. Je nach Kenntnis kann jeder sein eigenes Urteil bilden. Sehe hier auch nicht die Gefahr, das "Unwissende" gefährdet sein könnten.



  • @john-0 sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    @SeppJ sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    sondern dass das absolut gar nichts mit dem Thema zu tun hat.

    Es geht um das Thema: Wie beeinflusst protected das Design von Klassen in C++. Das Design von C++ Klassen wird eben nicht nur von der API sondern auch von der ABI beeinflusst.

    Nein. Es geht hier darum, der Threaderstellerin zuerst die wichtigen Ratschläge zu geben. Und da gilt für, mich dass die ABI in diesem Stadium des Lernens gar keine Bedeutung hat und die API eine große Bedeutung hat. In einem anderen Leserkreis wäre deine Diskussion sicherlich relevant, aber in diesem Kontext ist sie nicht zielführend, da sie unter Umständen auch zur Verwirrung beiträgt.



  • @zeropage sagte in Klassen in C++ Durchschnitt von zwei Zahlen berechnen:

    Mich juckt das auch nicht. Habe zwar niemanden ignoriert, aber ich finde es gut, wenn es auch solche Diskussionen gibt. Je nach Kenntnis kann jeder sein eigenes Urteil bilden. Sehe hier auch nicht die Gefahr, das "Unwissende" gefährdet sein könnten.

    Das Urteil, das ich mir aus diesen Diskussionen gebildet habe, ist menschlich, nicht fachlich. Und SeppJ hat es schon ziemlich gut beschrieben.
    Das sind so Diskussionen, auf die ich nicht wirklich Bock habe, weil sie zu 99,99% Dinge behandeln, die ich in meinen Quelltexten nicht habe. Und ich habe genug andere Dinge zu tun, um mich akademische Nischenprobleme zu kümmern.


  • Gesperrt

    Hallo, damit die Streitigkeiten mal ein Ende finden, ich wäre die Sache ungefähr so angegangen:

    #include <iostream>
    
    using namespace std;
    
    class Average
    {
    private:
        const bool exact;
        int32_t count = 0;
        int64_t sum = 0;
        double avg = 0;
    
    public:
        Average();
        Average(int32_t size);
        ~Average();
        void addElement(int32_t e);
        double getAvg();
    };
    
    Average::Average() : exact(true)
    {
    }
    
    Average::Average(int32_t size) : exact(false), count(size)
    {
    }
    
    Average::~Average()
    {
    }
    
    void Average::addElement(int32_t e)
    {
        if (exact)
        {
            count++;
            sum += e;
        }
        else
        {
            avg += e / (double)count;
        }
    }
    
    double Average::getAvg()
    {
        if (exact)
        {
            return sum / (double)count;
        }
        else
        {
            return avg;
        }
    }
    
    int main(int argc, char const *argv[])
    {
        Average a1;
        Average a2(3 * 10);
        int32_t vals[] = {
            -23, 456, -543};
        for (size_t i = 0; i < 10; i++)
        {
            for (const auto &e : vals)
            {
                a1.addElement(e);
                a2.addElement(e);
            }
        }
        cout.precision(17);
        cout << a1.getAvg() << "\n";
        cout << a2.getAvg() << "\n";
        double expected = -36.666666666666666;
        cout << expected << "\n";
        cout << abs(a1.getAvg() - expected) << "\n";
        cout << abs(a2.getAvg() - expected) << "\n";
        return 0;
    }
    
    

    Ich denke, das ist so richtig... Die Ausgabe ist bei mir (bei euch hoffentlich auch...):

    -36.666666666666664
    -36.666666666666686
    -36.666666666666664
    0
    2.1316282072803006e-14
    
    

    (Falls ich was übersehen hab, bitte Hinweise geben 🙂 Danke)



  • Mein Senf dazu:

    1. using namespace ... gehört nicht in Header Dateien
    2. fehlende const-correctness
    3. Warum keine Default-Initialisierung für exact?
    4. Warum ist exact const? Damit verhinderst du, dass Kopien erzeugt werden können, ist das so gewollt? Es ist privat und kann nur über den Konstruktor gesetzt werden, warum machst du das noch zusätzlich const?
    5. C-style casts (Zeile 50) in C++ sind meh

  • Gesperrt

    Danke fürs Feedback/Review @DocShoe ... 🙂

    Warum ich das mache? Weil ich es nicht besser wusste... Hast du einen Änderungsvorschlag? lg.



  • @EinNutzer0 Naja, schreibt @DocShoe doch. im Header kein using namespace sondern std:: vor die jeweiligen Sachen schreiben. Wobei du das nur in der main() hast, daher brauchst du im Header gar kein using namespace
    Die Member Funktionen, die const sein können, sollten das auch sein. Das betrifft vor allem deine Getter.
    Anstelle c-Style casts gäbe es auch C++ Alternative.

    Apropos c-Style Cast, noch ein paar Anmerkungen von mir:
    Vielleicht kannst du dein Programm auch so ändern, das gar nicht gecasted werden muss?
    Warum nimmt dein Rechner nur int entgegen? Kann es nicht sein, dass man auch einen Mittelwert von nicht ganzen Zahlen berechnen möchte?

    Was soll die Konvention mit dem exact? Wenn das false ist und die Anzahl der hinzugefügten Elemente nicht mit count übereinstimmt, ist der Mittelwert einfach falsch. Warum bietest du das überhaupt an, das als API ist maximal unintuitiv.

    Was soll der Konstruktor Parameter size? Von was ist das die size? Der Member heißt doch auch anders.

    Warum hast du einen Destruktor definiert?

    In deiner main iterierst du ja direkt über eine range und fügst die Elemente einzeln hinzu. Als Idee für eine Weiterentwicklung, vlt wäre es ja Sinnvoll, wenn dein Rechner direkt auf einer range arbeiten könnte.

    Und zum Schluss: Deine Übrprüfung in der main ist für Nachvolllziehbarkeit im Forum gut, aber für dich wäre es noch ein bisschen besser, wenn du das in Unit Tests ausgliedern würdest 😉


  • Mod

    Unter der Annahme (der Code ist wegen der schlechten Bezeichner recht unlesbar, daher nur Annahme), dass der exact-Parameter irgendwie zwischen zwei unterschiedlichen Strategien wählen soll: Nicht so. if-Abfragen, um zwischen verschiedenen Strategien wählen zu können haben viele Nachteile:

    • Muss an vielen Stellen konsistent gehalten werden -> Katastrophe buchstäblich vorprogrammiert
    • Nicht erweiterbar, wenn mehr Möglichkeiten gebraucht werden
    • Man schleppt überall den Müll von den nicht-benutzten Strategien herum (hier z.B. avg)
    • Laufzeitkosten
    • Schlecht lesbar, da jede einzelne Funktion alle Strategien enthält, und daher jede Funktion aufgeblasen ist und der Code für die verschiedenen Strategien immer abwechselnd durchmischt ist (hier gehören z.B. Zeile 54 und 42 zusammen, dazwischen ist aber Codezeile 50, die zu 37f. gehört)

    Ansonsten schreit der Numeriker in mir, dass exact einen weniger genauen Algorithmus benutzt.


  • Gesperrt

    Ja, ich verfolgte damit zwei unterschiedliche "Summierungsstrategien"...

    Ich werde das noch mal komplett überarbeiten und melde mich später nochmal. 🙂 Hohe Fehleranfälligkeit, nicht erweiterbar und unnötige Laufzeitanforderung leuchtet mir sofort ein.


  • Gesperrt

    Bitte nicht hauen 🙃 , aber habe ich jetzt noch etwas übersehen?

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    class Average
    {
    private:
    public:
        virtual void addElement(double e) = 0;
        virtual double getAvg() = 0;
    };
    
    class ExactAverage : public Average
    {
    private:
        uint32_t count = 0;
        double sum = 0;
    
    public:
        ExactAverage(){};
        void addElement(double e)
        {
            count++;
            sum += e;
        }
        double getAvg()
        {
            return sum / count;
        }
    };
    class NormalAverage : public Average
    {
    private:
        const uint32_t numberOfElements;
        double avg = 0;
    
    public:
        NormalAverage(uint32_t numberOfElements) : numberOfElements(numberOfElements){};
        void addElement(double e)
        {
            avg += e / numberOfElements;
        }
        double getAvg()
        {
            return avg;
        }
    };
    
    int main(int argc, char const *argv[])
    {
        const uint32_t n = 3 * 10;
        std::vector<Average *> myAverages;
        myAverages.push_back(new ExactAverage());
        myAverages.push_back(new NormalAverage(n));
        double vals[] = {
            -23.45, 456.7, -543.21};
        for (size_t i = 0; i < 10; i++)
        {
            for (size_t j = 0; j < sizeof(vals) / sizeof(vals[0]); j++)
            {
                for_each(myAverages.begin(), myAverages.end(), [&](Average *a)
                         { a->addElement(vals[j]); });
            }
        }
        std::cout.precision(17);
        for_each(myAverages.begin(), myAverages.end(), [&](Average *a)
                 { std::cout << a->getAvg() << "\n"; });
        return 0;
    }
    
    

    Das new geht nicht, oder?


Anmelden zum Antworten