Wertebereich Datentypen



  • Hallo liebe C++-Gemeinde,

    Heute mal die Grundsätzliche Frage wie ihr ran gehen würdet um folgendes zu erreichen:

    Ich habe sehr viele long Variablen und muss über eine Datenbankauswertung immer Zahlen der verschiedenen Typen (int, unsigned long, etc) hinzuaddieren.
    Dabei kann es mir passieren, dass ich über den maximalen Wertebereich von long hinauslaufe, was bedeutet, dass ich plötzlich negative Werte habe, wo eigentlich Milliarden Positive stehen sollten.

    Wie würdet ihr das Problem mit dem Überlauf regeln. ??
    Ich habe bereits eine Konstante, die den maximalen Wertebereich von long beinhaltet. Aber

    // Freies Beispiel
    long Aktuell(3_UNTER_MAXIMUM);
    if (( Aktuell + 5 ) > MAXIMAL_LONG) // 5 Kann jegmöglicher ganzzahliger Type sein
      {
          Aktuell = MAXIMAL_LONG;
      }
    

    funktioniert ja leider nicht, weil ja der Compiler bereits bei "Aktuell + 5" den Wertebereich überschreitet und den Werte 2_UEBER_MINIMUM (also z.B. -9 Milliarden) hat.

    Wie stelle ich bestmöglich fest, ob bei einer Addition mein Maximaler Wertebereich überschritten wird? Durch die Addition von "-10" kann natürlich auch der Wertebereich bei einer Addition unterschritten werden. Wie handelt ihr solche Fälle mit ab?



  • Ich weiss nicht ob es elegantere Moeglichkeiten gibt, aber fuer Overflow kann man es wie folgt machen:

    #include <climits>
    #include <iostream>
    
    using std::cout;
    using std::endl;
    
    int main()
    {
    	long current_value = LONG_MAX - 100;
    
    	long a = 50;
    	if ( LONG_MAX - current_value < a )
    		cout << "Wir haben einen Ueberlauf" << endl;
    	else
    		current_value += a;
    
    	long b = 150;
    	if ( LONG_MAX - current_value < b )
    		cout << "Wir haben einen Ueberlauf" << endl;
    	else
    		current_value += b;
    }
    

    Das sollte man relativ leicht fuer Underflow anpassen koennen.



  • z.B. schrittweise Herantasten:

    for(int i=1; i<=5; ++i)
    {
        if( Aktuell+i == MAXIMAL_LONG )
        {
             Aktuell = MAXIMAL_LONG;
             break;
        }
    }
    


  • Mach die Berechnungen als mit einer long long Hilfsvariablen.
    Vergiss aber nicht das csten auf der rechten Seite.
    Die Hilfsvariablen kannst du dann auf überlauf prüfen.

    Eine andere Möglichkeit ist, nach der Addition zu schauen, ob der neue Wert kleiner dem alten Wert ist.

    if (current_value > (current_value + s))  // für positive a
      Überlauf
    ...
    


  • Für den Fall, dass Du ausschließlich positive Werte zu addieren hast, geht:

    // Freies Beispiel
    long Aktuell(3_UNTER_MAXIMUM);
    if (( Aktuell + X ) < Aktuell) // X Kann jegmöglicher ganzzahliger Type sein
      {
          Aktuell = MAXIMAL_LONG;
      }
    


  • Belli schrieb:

    if (( Aktuell + X ) < Aktuell) // X Kann jegmöglicher ganzzahliger Type sein
    

    Kann man u.U. machen, man sollte aber wissen, dass das Überlaufverhalten von signed-Typen undefiniert ist.



  • Bashar schrieb:

    ...man sollte aber wissen, dass das Überlaufverhalten von signed-Typen undefiniert ist.

    Und von "unsigned" nicht?
    Bitte genauer erklären oder Lektüre anbieten.



  • Erstmal danke für die vielen Antworten.

    Einige der Möglichkeiten hatte ich auch schon in Betracht gezogen.

    Werde jetzt einfach mal ein wenig 'rumspielen' um zu sehen wie ich es am besten mache. Und was mir die beste Performance bringt.

    Mfg



  • stefanjann schrieb:

    Bashar schrieb:

    ...man sollte aber wissen, dass das Überlaufverhalten von signed-Typen undefiniert ist.

    Und von "unsigned" nicht?

    Genau.

    Bitte genauer erklären oder Lektüre anbieten.

    C++-Standard, 3.9.1p4: «Unsigned integers, declared unsigned , shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.»



  • Einfach umformen:

    if (( Aktuell) > (MAXIMAL_LONG - 5)) // 5 Kann jegmöglicher ganzzahliger Type sein
    {
        Aktuell = MAXIMAL_LONG;
    }
    


  • Nachtrag:
    Wenn die Zahl, die statt "5" dasteht auch negativ sein kann, hat diese Lösung natürlich prinzipiell ein Problem - das müsste man dann vorher auch nochmal prüfen.



  • Bashar schrieb:

    undefiniert

    Nein, ich bin mir ziemlich sicher, dass es implementation-defined ist.



  • 314159265358979 schrieb:

    Bashar schrieb:

    undefiniert

    Nein, ich bin mir ziemlich sicher, dass es implementation-defined ist.

    Besser wäre, du wärst dir ganz sicher. Aber dazu müsste man ja mal nachschlagen, bevor man irgendwas behauptet...



  • DirkB schrieb:

    Eine andere Möglichkeit ist, nach der Addition zu schauen, ob der neue Wert kleiner dem alten Wert ist.

    if (current_value > (current_value + s))  // für positive a
      Überlauf
    ...
    

    Das ist nicht nur undefiniert, sondern wird für positive s auch von realen Compilern wegoptimiert. Auf keinen Fall benutzen.


Anmelden zum Antworten