Überlaufe

Bei einigen mathematischen Fragestellungen muss sich feststellen lassen, ob Operationen wie die Addition, Subtraktion oder Multiplikation den Zahlenbereich sprengen, also etwa den Ganzzahlenbereich eines Integers von 32 Bit verlassen. Passt das Ergebnis einer Berechnung nicht in den Wertebereich einer Zahl, so wird dieser Fehler standardmäßig nicht von Java angezeigt; weder der Compiler noch die Laufzeitumgebung melden dieses Problem. Es gibt auch keine Ausnahme, Java hat keine eingebaute Überlaufkontrolle.

Beispiel

Mathematisch gilt a × a / a = a, also zum Beispiel 100 000 × 100 000 / 100 000 = 100 000. In Java ist das anders, da wir bei 100 000 × 100 000 einen Überlauf im int haben.

System.out.println( 100000 * 100000 / 100000 );     // 14100

liefert daher 14100. Wenn wir den Datentyp auf long erhöhen, indem wir hinter ein 100 000 ein L setzen, sind wir bei dieser Multiplikation noch sicher, da ein long das Ergebnis aufnehmen kann.

System.out.println( 100000L * 100000 / 100000 );    // 100000

Hinweis

Ein Test auf Überlauf könnte aussehen: boolean canMultiply(int a, int b) { return a * b / b == a; } reichen. Doch eine JVM kann das zu return a == a; optimieren und somit zu return true; machen, sodass der Test nicht funktioniert.

Überlauf erkennen

Für eine Operation wie die Addition oder Subtraktion lässt sich relativ leicht erkennen, ob das Ergebnis über das Ziel hinausschießt. Eine Möglichkeit ist, bei der Addition zweier ints diese erst auf long zu bringen und dann den long mit der Konstanten Integer.MAX_VALUE/Integer.MIN_VALUE zu vergleichen. Aber über die Interna brauchen wir uns keine großen Gedanken machen, denn ab Java 8 kommen neue Methoden hinzu, die eine Überlauferkennung ermöglichen. Die Methoden gibt es in Math und StrictMath:

· static int addExact(int x, int y)

· static long addExact(long x, long y)

· static int subtractExact(int x, int y)

· static long subtractExact(long x, long y)

· static int multiplyExact(int x, int y)

· static long multiplyExact(long x, long y)

· static int toIntExact(long value)

Alle Methoden werfen eine ArithmeticException, falls die Operation nicht durchführbar ist, die letzte, wenn (int)value != value ist. Leider deklariert Java keine Unterklassen wie UnderflowException oder OverflowException, und Java meldet nur alles vom Typ ArithmeticException mit der Fehlermeldung „xxx overflow“, auch wenn es eigentlich ein Unterlauf ist:

System.out.println( subtractExact( Integer.MIN_VALUE, 1 ) ); // ArithmeticException

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert