# Auf Überlauf prüfen



## Jenny (6. Aug 2009)

Hallo Leute,
Wie prüfe ich am geschicktesten ob bei einer Differenz bzw. Addition von zwei Ganzahltypen (long, integer) ein Überlauf geschieht? Was ich im Forum zum Thema gefunden habe war ein ziemliches Kuddelmuddel. Ist doch aber ein Problem das dauernd auftritt. Dafür müsste es doch eigentlich eine Standartlösung geben, oder?

schöne Grüße


----------



## Ark (6. Aug 2009)

Du kannst ja das Overflow-Flag nachprogrammieren. ^^

Ark


----------



## ARadauer (6. Aug 2009)

ist a + b >  max?

wenn(max - a) < b
dann wäre es soweit oder?

```
public class Test {


   public static void main(String[] args) {
   int a = 2147483647;
   int b = 100;
   
   System.out.println(ueberlauf(a, b));
      

   }
   
   public static  boolean ueberlauf(int a, int b){
      return ((Integer.MAX_VALUE-a) < b);
   }
   
  
}
```


----------



## Jenny (6. Aug 2009)

Das mit dem Overflow-flag ist mir für den Moment zu hoch. Die Lösung von ARadauer berücksichtigt leider nicht negative Werte. Also erst kucken ob negativ oder ob beide negativ - nee, welcher operand negativ ist und dann entsprechend?


----------



## Landei (6. Aug 2009)

Der Aufwand der Überprüfung lohnt sich meistens nicht, denn im Allgemeinen kann man ja abschätzen, in welcher Größenordnung sich die Werte bewegen.

Wenn du Angst hast, dass ints überlaufen, nimm longs. 
Wenn du Angst hast, dass longs überlaufen, nimm BigInteger. 
Wenn du Angst hast, dass BigIntegers überlaufen, suche einen Psychater deines Vertrauens auf, denn dann bist du paranoid...


----------



## ice-breaker (6. Aug 2009)

K, also welche Fälle haben wir:

a = pos, b = pos, *Überlauf bei:* neg. Wert
a = pos, b = neg, *Überlauf bei:* abhängig von den Werten 
a = neg, b = pos, *Überlauf bei:* abhängig von den Werten 
a = neg, b = neg, *Überlauf bei:* pos. Wert

Nun betrachten wir was bei Fall 2 passiert:

a > abs(b), kein Überlauf möglich
a < abs(b), es gibt einen Überlauf

Fall3:
kann auf Fall 4 abgebildet werden indem a mit b vertauscht wird


----------



## Painii (6. Aug 2009)

a = pos, b = neg, *Überlauf bei:* abhängig von den Werten
a = neg, b = pos, *Überlauf bei:* abhängig von den Werten

Ich nehme an du willst beide wieder in den gleichen Datentyp packen (also nicht int = long+long, sondern int=int+int).
Dann kann hier doch kein Überlauf auftreten.
wäre a+(-abs(b))>max, dann müsst ja schon a>max+abs(b)-> a>max, was nicht geht.
Genauso umgekehrt indem man a und b vertauscht.
Ist also einer der beiden negativ und der andere positiv kannst du eigentlich keinen Überlauf erzeugen.

Bei beiden positiv oder beiden negativ wie ice-breaker gesagt hat.

Oh, und natürlich mit int signed, sonst würde das von ice-breaker auch gelten weil ja dann a=1, b=-2 a+b=-1 wäre und -1 bei unsigned ja wieder irgendwo ganz groß ist.


----------



## ice-breaker (6. Aug 2009)

Painii hat gesagt.:


> Ist also einer der beiden negativ und der andere positiv kannst du eigentlich keinen Überlauf erzeugen.



ach sorry, ich habe zu weit gedacht 
meine Regeln galten dafür, wann die Zahl neg. wird



Painii hat gesagt.:


> Oh, und natürlich mit int signed, sonst würde das von ice-breaker auch gelten weil ja dann a=1, b=-2 a+b=-1 wäre und -1 bei unsigned ja wieder irgendwo ganz groß ist.


Java kennt doch nur signed-Datentypen, oder hab ich was verpasst ???:L


----------



## Jenny (6. Aug 2009)

Die Regeln für 2 und 3 gelten aber durchaus bei der Differenz. 

a = pos, b = pos, Überlauf bei: nicht möglich
a = pos, b = neg, Überlauf bei: abhängig von den Werten 
a = neg, b = pos, Überlauf bei: abhängig von den Werten 
a = neg, b = neg, Überlauf bei: nicht möglich


----------



## Painii (6. Aug 2009)

ice-breaker hat gesagt.:


> Java kennt doch nur signed-Datentypen, oder hab ich was verpasst ???:L



Ich schau mir gerade etwas C und seine ekligen Pointer an... daher der Hinweis.
In Java gibts das natürlich nicht. (Da hab ich dann zuweit gedacht  )


----------



## Spacerat (7. Aug 2009)

bis einschliesslich int funktioniert folgendes... (Beispiel mit Byte)
	
	
	
	





```
byte xb = 127;
byte yb = 127;
short xs = (short) (xb & 0xff);
short ys = (short) (yb & 0xff);
short es = xs + ys;
boolean overflow = (es & 0x100) != 0;
```
Die anzahl der f's ändert sich natürlich von datentyp zu datentyp.
Allgemein kann man aber auch mit isolierten N-Flags arbeiten (Beispiel mit Byte).
	
	
	
	





```
byte xb = 127;
byte yb = 127;
boolean carry = ((xb & 0x80) ^ (yb & 0x80)) != 0;
byte eb = xb + yb;
boolean overflow = carry ^ ((eb & 0x80) != 0);
```


----------



## Ark (7. Aug 2009)

Ist das nicht etwas am Thema vorbei? Immerhin geht es hier auch um long, und da wird es schwierig, mal eben einen größeren Datentyp zu finden (außer BigInteger, blabla). Hochsprachen haben gegenüber Assemblern eben doch einige Nachteile. ^^

Ark


----------



## Spacerat (7. Aug 2009)

der erste Teil vllt. Der 2. Teil dagegen funktioniert ohne Bit-Expansion und daher auch bei long. Vllt. hätte ich deswegen auch long im 2. Beispiel verwenden sollen. Das ist mir im übrigen auch erst viel später eingefallen. Ich hol das mal nach
	
	
	
	





```
long xl = Long.MAX_VALUE;
long yl = Long.MAX_VALUE;
boolean carry = ((xl & 0x8000000000000000L) ^ (yl & 0x8000000000000000L)) != 0;
long el = xl + yl;
boolean overflow = carry ^ ((el & 0x8000000000000000L) != 0);
```
...seht ihr? Schon viel unübersichtlicher .


----------



## DrZoidberg (8. Aug 2009)

Funktioniert aber leider nicht.

[Java]
byte xb = -1;
byte yb = -1;
boolean carry = ((xb & 0x80) ^ (yb & 0x80)) != 0;
byte eb = (byte)(xb + yb);
boolean overflow = carry ^ ((eb & 0x80) != 0);
System.out.println(overflow);
[/Java]

Da kommt true raus.


----------



## Spacerat (8. Aug 2009)

...und Bauz... da hätte mich doch fast einer erwischt.
Ok... überredet... hier die letzten 2 Versionen:
short:
	
	
	
	





```
short xs = -1;
short ys = -1;
boolean carry = ((xs & 0x8000) ^ (ys & 0x8000)) != 0;
short es = (short) (xs + ys);
boolean overflow = carry ^ ((es & 0x8000) != 0);
```
int:
	
	
	
	





```
int xi = -1;
int yi = -1;
boolean carry = ((xi & 0x80000000) ^ (yi & 0x80000000)) != 0;
short ei = xi + yi;
boolean overflow = carry ^ ((ei & 0x80000000) != 0);
```
Mit char würde das im übrigen auch gehen. Hab' ich aber weggelassen, da es
1. das gleiche wäre wie bei short.
2. unlogisch wäre, wenn man bedenkt, das man mit Zeichen eigentlich nicht rechnen kann (a+b bleibt a+b und wird nicht 195 oder sowas  ).
3. char hat, wenn man es genau nimmt, kein Negativ-Flag.

@Edit: Mom... faktisch hat mich da jemand sogar erwischt... Die Berechnung von overflow muss ja vom Carry-Flag abhängig gemacht und nicht damit verknüpft werden 

```
boolean overflow = (!carry)? (eb & 0x80) != (xb & 0x80) : false;
```
...gut das es Leute gibt, die einem nicht gleich immer alles glauben.
@Edit 2: Ich glaub' 'nu habbichs.


----------

