Division durch NULL verhindern



  • Hi,

    ich habe ein Problem, ich soll ein Prog schreiben, was 2 Integer-Werte einliest. Der erste Integer-Wert soll durch den zweiten dividiert und das Ergebniss dann ausgegeben werden.

    Damit habe ich kein Problem. Nun soll ich aber die die Division durch verhindern, ohne dass ich die if-Abfrage, bzw. die Logischen Operatoren, nehmen darf.

    Kann mir hierzu jemand eine Möglichkeit nenne, wie ich das Problem lösen kann?

    Danke schoneinmal im voraus.
    Regin



  • try
    {
        erg = z1 / z2;
    }
    catch(...)
    {
        std::cout << "Division durch Null nicht moeglich!";
    }
    


  • Das geht unter C++ nicht.

    Das was FireFlow geschrieben hat, KANN funktionieren, MUSS aber nicht.

    Also ich würde sagen deine Aufgabe ist unlösbar, oder darfst über den Standard hinaus was machen?



  • standar-t: Wieso *kann* es funktionieren, *muss* aber nicht?

    Darf man den ternären Operator benutzen?



  • Michael E. schrieb:

    standar-t: Wieso *kann* es funktionieren, *muss* aber nicht?

    Darf man den ternären Operator benutzen?

    Bei mir ist das auch eine logische Operation / Ausdruck, ist ja nur die "Kurzform" von if-else.

    Ich hab mal nachgeschaut im VC 7.1: Wenn man keine Optimierung ausgewählt hat wird eine Exception geworfen, hat man aber irgendeine (egal welche) aktiviert wird zwar auch eine geworfen, diese aber nicht mehr verarbeitet, keine Ahung warum.

    Ich bin mir net sicher ob es der Standard vorschreibt, aber ich glaube nein.



  • Michael E. schrieb:

    standar-t: Wieso *kann* es funktionieren, *muss* aber nicht?

    Darf man den ternären Operator benutzen?

    Das hängt vom Compiler ab ob er für CPU-Exceptions eine C++ Exception generiert.



  • Michael E. schrieb:

    standar-t: Wieso *kann* es funktionieren, *muss* aber nicht?

    Darf man den ternären Operator benutzen?

    Soweit ich weiß definiert der Standard nicht was bei einer Teilung durch 0 passiert.

    Das von FireFlow beschiebene Verhalten kann man unter dem VC beobachten. Was passiert ist, dass als erstes eine "Win32 Structured Exception" geworffen wird und zwar EXCEPTION_INT_DIVIDE_BY_ZERO (oder EXCEPTION_FLT_DIVIDE_BY_ZERO für floats) diese biegt der VC nun auf eine C++ Exception des Types unsigned um wenn ein spezielles Ausnahmebehandlungssystem benutzt wird (asyncronisch glaub ich). Diese wird dann mit catch(...) gefangen.

    Unter VC und BC kann mann auch die "Win32 Structured Exception" direkt fangen indem mann __try und __except einsetzt. Unter MinGW ist es glaub ich nicht möglich ohne inline ASM diese Exceptions zu fangen. MinGW wandet sie später in Signals um und zwar SIGFPE.

    Aber generel kann man sagen, dass jeder Compiler ein Program abstürzten lässt wenn nichts besonderes unternommen wird. Wenigstens auf einem Punkt Einigkeit. 🕶

    Damit habe ich kein Problem. Nun soll ich aber die die Division durch verhindern, ohne dass ich die if-Abfrage, bzw. die Logischen Operatoren, nehmen darf.

    Nun wenn das Program abstürzt hast du die Division ja verhindert.

    Was soll den eignelich passieren wenn eine Division durch 0 geschiet? Was du auch noch machen könntest wäre

    cout<<((z1*!!z2) / ((1-(!!z2)) + z2*(!!z2)))<<endl;
    

    Sollte ! verboten sein dann geht auch noch

    cout<<((z1*(bool)z2) / ((1-(bool)z2) + z2*(bool)z2))<<endl;
    

    Herauszufinden was dieser Ausdruck bei einer Teilung durch 0 macht überlasse ich dem Fragesteller als Aufgabe allerdings glaub ich kam, dass der Lehrer darauf hinaus will.



  • int a;
    int b;
    cin >> a >> b;
    while( a != 0) {
      cout << b/a << endl;
      break;
    }
    

    Wahrlich nicht schön, aber ohne if und logische Operatoren...



  • while == if



  • 🙂
    Was für einen Vergleichsoperator nutzt Du denn für diese Gleichung ?

    In dem Fall ist das while zwar wie ein if verwendet, aber ein while ist kein if. (alle Schleifen lassen sich mit if und goto herstellen und dennoch würde keiner Behaupten, dass if/goto dasselbe wie for/while/do{}while ist)



  • niemand schrieb:

    🙂
    Was für einen Vergleichsoperator nutzt Du denn für diese Gleichung ?

    Das ist ja mein Problem, das mit den Abfragen und den dazugehörigen Vergleichsoperatoren, kommen erst in den nächsten Stunden drann, und wir dürfen nur das verwenden was wir bis hierher haben. Und das ist nicht viel.
    Das mit den try-Blöcken kommt auch erst später.

    FireFlow schrieb:

    Bei mir ist das auch eine logische Operation / Ausdruck, ist ja nur die "Kurzform" von if-else.

    Ich haben nicht logische Operation, sondern logische Operatoren (!, &&, ||) geschrieben. Eigentlich meinte Vergleichsoperatoren.

    Mein erster Ansatzt war es mit Typecasting zu probieren, aber das hat nicht so funktioniert wie ich mir gedacht habe.



  • Ben04 schrieb:

    Soweit ich weiß definiert der Standard nicht was bei einer Teilung durch 0 passiert.

    Der Standard definiert es, und zwar als "undefined behaviour" (5.6.4 [expr.mul]). Man beachte: undefined, nicht implementation defined.



  • 7H3 N4C3R schrieb:

    Ben04 schrieb:

    Soweit ich weiß definiert der Standard nicht was bei einer Teilung durch 0 passiert.

    Der Standard definiert es, und zwar als "undefined behaviour" (5.6.4 [expr.mul]). Man beachte: undefined, nicht implementation defined.

    Liegt undefinertes Verhalten denn nicht ausserhalb des Standards und somit in den Händen der Compilerherrsteller? Irgendwie versteh ich den Unterschied den du da machst nicht. 😕



  • Undefiniertes Verhalten ist undefiniert. Jedes Programm, das undefiniertes Verhalten enthält, ist kein gültiges C++ Programm. Punkt.

    Spekulationen, was ein bestimmter Compiler damit nun macht, sind völlig irrelevant. Er wäre völlig legitim, Dir für undefiniertes Verhalten die Festplatte zu formatieren 😉

    Implementation-Defined heißt dagegen: Jeder Compiler/Bibliothekshersteller liefert ein für sich definiertes, aber nicht allgemeingültiges und für sich dokumentiertes Verhalten.



  • Er wäre völlig legitim, Dir für undefiniertes Verhalten die Festplatte zu formatieren

    det wär gemein 😡



  • Reigin schrieb:

    Mein erster Ansatzt war es mit Typecasting zu probieren, aber das hat nicht so funktioniert wie ich mir gedacht habe.

    wenn du nach bool casten darfst, muss es aber gehen.

    ich will a/b schaffen.
    wenn b==0, soll b erst verändert werden.

    also
    a/(b+(b==0))
    a/(b+!bool(b))
    a/(b+(1-bool(b)))

    man könnte auch anders versuchen, festzustellen, ob b==0
    sagen wir mal, ich will alle gesetzten bits auf eins zusammenwerfen.
    (b)|(b>>16)
    wirft schonmal die 32 bits auf 16 zusammen.
    also sagen wir mal
    int c=b;
    c=(c)|(c>>16);
    c=(c)|(c>>8);
    c=(c)|(c>>4);
    c=(c)|(c>>2);
    c=(c)|(c>>1);
    nu ist c=bool(b)
    und wie gehabt
    a/(b+(1-c))



  • oder einfach ein switch

    switch(b)
    {
      case 0: cout << "geht nich" << endl;
      default: cout << a/b << endl;
    };
    


  • 7H3 N4C3R schrieb:

    Spekulationen, was ein bestimmter Compiler damit nun macht, sind völlig irrelevant. Er wäre völlig legitim, Dir für undefiniertes Verhalten die Festplatte zu formatieren 😉

    Sprich das Verhalten ist Festplattenreformation und das Auftretten dieses Verhalten hängt von der Implementierung ab.

    7H3 N4C3R schrieb:

    Implementation-Defined heißt dagegen: Jeder Compiler/Bibliothekshersteller liefert ein für sich definiertes, aber nicht allgemeingültiges und für sich dokumentiertes Verhalten.

    Das heist der Unterschied besteht darin, dass hier der Herrsteller irgendwo das Verhalten dokumentiert hat und bei undefiniertem Verhalten nicht? Ach was für eine Paragrafenreiterei.



  • Implementation-Defined
    Falsch nicht das er dokumentiert hat d heißt nämlich wenn er es nicht tut is auch gut, sondern er muß ein eindeutiges Verhalten implementiern und dokumentieren.

    undefiniertes Verhalten,
    da kann er was implemtieren und nicht dokumentieren oder implementieren und nicht dokumentieren oder nichts tun, oder sich darauf verlassen das das OS was tut.

    Und das ganze ist nicht nur Paragraphen-Reiterei



  • Ben04 schrieb:

    7H3 N4C3R schrieb:

    Spekulationen, was ein bestimmter Compiler damit nun macht, sind völlig irrelevant. Er wäre völlig legitim, Dir für undefiniertes Verhalten die Festplatte zu formatieren 😉

    Sprich das Verhalten ist Festplattenreformation und das Auftretten dieses Verhalten hängt von der Implementierung ab.

    7H3 N4C3R schrieb:

    Implementation-Defined heißt dagegen: Jeder Compiler/Bibliothekshersteller liefert ein für sich definiertes, aber nicht allgemeingültiges und für sich dokumentiertes Verhalten.

    Das heist der Unterschied besteht darin, dass hier der Herrsteller irgendwo das Verhalten dokumentiert hat und bei undefiniertem Verhalten nicht? Ach was für eine Paragrafenreiterei.

    Das ist sicher verwirrend, aber die Begriffe sind Teil des C++-Standards und daher nicht frei wählbar, sondern genau definiert.

    Der Unterschied liegt darin, das der Herrsteller das Verhalten festlegen kann, aber es muß halt definiert sein, denn implementation-defined behavior gibt dem Hersteller Spielraum für die Implementation. So sind zum Beispiel die typeinfo-Inhalte mehr oder weniger implementation-defined, aber es ist natürlich möglich sie sinnvoll (aber nicht immer portabel) zu nutzen. 🙂

    Der Standard sagt daher zu implementation-defined behavior (iso14882: 1.3.5) das es sich um Verhalten in einem korrekten Programm und korrekten Daten handelt, das auf dokumentierten Implementations-Details basiert, für undefined behavior (iso14882: 1.3.12) hingegen Verhalten das in einem fehlerhaften Programm oder bei fehlerhaften Daten auftritt und für das unspezifiziert ist, was zu passieren hat.

    Die Unterscheidung macht Sinn und lässt sich gekürzt zusammenfassen mit implementation-defined behavior ist akzeptabel, undefined behavior gibt ein Bug-Ticket. 🤡



  • ich progge schon seit jahren schon mit undefiniertem verhalten. meinem computer ist dabei aber noch nichts schlimmes passiert.
    also halb so wild. 🕶


Anmelden zum Antworten