C++ - Aufgabe: Programmierer gesucht. Gegen Geld!


  • Mod

    DocShoe schrieb:

    Man sollte in get_mean prüfen, ob N ungleich 0 ist.

    Und wenn es das ist? Mein Programm macht dann schon alles richtig, ganz ohne Prüfung.



  • Ja, aber deine mean Klasse nicht. Sie lässt Fehlbenutzung ohne Fehlerbehandlung zu, das könnte man noch verbessern.


  • Mod

    DocShoe schrieb:

    Ja, aber deine mean Klasse nicht. Sie lässt Fehlbenutzung ohne Fehlerbehandlung zu, das könnte man noch verbessern.

    😕 Mein Programm lässt alles die Klasse machen. Hast du es mal ausprobiert? Welche Art von Fehler wäre N=0 und wie würdest du das behandeln, wenn nicht so, wie ich?



  • SeppJ schrieb:

    DocShoe schrieb:

    Ja, aber deine mean Klasse nicht. Sie lässt Fehlbenutzung ohne Fehlerbehandlung zu, das könnte man noch verbessern.

    😕 Mein Programm lässt alles die Klasse machen. Hast du es mal ausprobiert? Welche Art von Fehler wäre N=0 und wie würdest du das behandeln, wenn nicht so, wie ich?

    Ja, dein Programm macht alles richtig, ich habe nie etwas anderes behauptet. Das Einzige, das ich auszusetzen habe, ist, dass die Methode get_mean ohne mit der Wimper zu zucken durch 0 teilt. Das Doofe an der Division durch 0 ist, dass man die nur durch einen globalen Error Handler behandeln kann, was ziemlicher Mist ist.
    Ich würde in dem Fall entweder NaN zurückgeben oder eine exception werfen. Du kannst jetzt natürlich argumentieren, dass man vorher mit get_count() prüfen soll, ob mindestens ein Eingangswert vorliegt, aber da scheiden sich die Geister. Auf der einen Seite hat man das C++ Prinzip you only pay for what you use, auf der anderen Seite sind undefinierte mathematische Operationen blöd zu debuggen, dass ich mir da oft eine komfortablere Lösung als _matherr wünsche. Daher mein Einwand.

    Nachtrag:
    Programm starten, Eingabe "abc" => Bumm.


  • Mod

    ??? Aber es wird doch NaN zurück gegeben!



  • Jetzt haste mich soweit, ich hab´s mal übersetzt und laufen lassen. Wenn ich keine gültige Eingabe mache wirft mir die Laufzeitumgebung drei "unknown software exceptions" (2x 0xc0000090, 1x 0xc0000027). Compiler ist Codegear RAD Studio 2007, OS ist WinXP. Im Debugger erhalte ich an der Stelle wenigstens noch den Hinweis "floating point invalid operation".

    class Mean 
    { 
      unsigned long N; 
      double sum; 
    public: 
      Mean() : N(0), sum(0) {} 
      void add(double value) { sum += value; ++N; } 
      unsigned long get_count() const { return N; } 
      double get_mean() const { return sum / N; } 
      void clear() { sum = 0; N = 0; } 
    }; 
    
    int main()
    {
      // laufen interessanterweise durch, sowohl t1 und t2 sind aber 0.
      int t1 = 0.0 / 0;  // Ergebnis t1 = 0
      int t2 = 0.0 / 0L; // Ergebnis t2 = 0
      int t3 = t1 / t2;  // Software Exception 0xC0000090
    
      Mean mean;
      mean.get_mean(); // Software Exception 0xC0000090
    }
    

    Lustigerweise darf ich im Quelltext durch die Konstante 0 teilen, aber nicht durch Variablen mit Wert 0. Warum läuft das bei dir durch?

    PS:
    Verhalten aktualisiert in C++11? Mein Compiler kann nur C++03.


  • Mod

    Nun, Floating Point Verhalten ist implementation defined. Aber welche Implementierung benutzt denn nicht IEEE floating point? Hast du irgendeine Mathematikoptimierung (beim GCC -ffast-math) angeschaltet? Die Optimieren nämlich so, dass die Sonderwerte nicht auftreten können.

    Integerdivision durch Null ist aber eine floating-point exception, das ist korrekt. Bei t1 und t2 sollte auf der rechten Seite NaN rauskommen, was dann implementation defined in einen int umgewandelt wird. Bei t3 könnte dann alles mögliche rauskommen. In der Regel 1, außer beim ersten Schritt kam 0 für t1 und t2 raus, dann sollte das eine Division durch 0 geben.
    Den Fehler in Zeile 21 kann ich absolut nicht nachvollziehen, außer, dass eben vorher schon eine Exception aufgetreten ist und danach eben nichts mehr stimmt.

    Was gibt denn

    int main()
    {
      Mean mean;
      std::cout << mean.get_mean(); // Software Exception 0xC0000090
    }
    

    ?

    P.S.: Prinzipiell ist das alles implementation defined oder gar undefined, ich beschreibe bloß das Verhalten, das ich kenne.



  • Ich habe mal in den Projekteinstellungen nachgeschaut, da sind "Schnelle Gleitkommaoperationen" aktiviert (Default-Einstellungen). Habe im Moment keine Lust, das jetzt ohne die Options zu prüfen, mach´ ich vielleicht später mal. Sooo wichtig ist das jetzt nun auch wieder nicht. Aber du siehst, dass diese ganze Problematik mit einer expliziten Überprüfung gegen 0 nicht entsteht. Wenn ich nur dann sicherstellen kann, dass mein Programm nur mit bestimmten Projekteinstellungen funktioniert, dann bau ich lieber eine Abfrage mehr ein.

    int main()
    {
      Mean mean;
      std::cout << mean.get_mean(); // Software Exception 0xC0000090
    }
    

    Wirft in get_mean() eine "unknown software exception". Ich habe bei meinen Tests für verschiedene Testläufe einzelne Zeilen auskommentiert und nur das Gesamtergebnis gepostet, das Ergebnis kann also nicht durch UB verfälscht worden sein.


  • Mod

    Aber wie reagierst du auf 0? Mit einer Exception?

    Nein, das ist einfach ein Fehler beim Übersetzen, wenn man schnelle Gleitkommarithmetik aktiviert, obwohl NaN im Programm vorkommen kann. Das ist eine höchst gefährliche Einstellung, da sie, wie du siehst, das Programmverhalten verändert. So etwas darf nie default sein.

    Sonst könntest du dich auch beschweren, dass ein Compileroption wie -Dcout=cin ein Programm durcheinander bringt.



  • SeppJ schrieb:

    Aber wie reagierst du auf 0? Mit einer Exception?

    Nein, ich gebe NaN zurück.

    SeppJ schrieb:

    Nein, das ist einfach ein Fehler beim Übersetzen, wenn man schnelle Gleitkommarithmetik aktiviert, obwohl NaN im Programm vorkommen kann. Das ist eine höchst gefährliche Einstellung, da sie, wie du siehst, das Programmverhalten verändert. So etwas darf nie default sein.

    Sonst könntest du dich auch beschweren, dass ein Compileroption wie -Dcout=cin ein Programm durcheinander bringt.

    Sehen die bei Codegear wohl anders, wenn das deren Default Einstellung ist. Gut, jetzt haben wir beide unseren Standpunkt mit unterschiedlichen Voraussetzungen.


Anmelden zum Antworten