{"id":1374,"date":"2012-06-16T14:52:10","date_gmt":"2012-06-16T12:52:10","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=1374"},"modified":"2012-06-16T14:52:10","modified_gmt":"2012-06-16T12:52:10","slug":"berlaufe","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2012\/06\/berlaufe\/","title":{"rendered":"&Uuml;berlaufe"},"content":{"rendered":"<p>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\u00e4\u00dfig nicht von Java angezeigt; weder der Compiler noch die Laufzeitumgebung melden dieses Problem. Es gibt auch keine Ausnahme, Java hat keine eingebaute \u00dcberlaufkontrolle.<ins datetime=\"2012-06-16T13:10\" cite=\"mailto:Christian\"><\/ins><\/p>\n<p>Beispiel<ins datetime=\"2012-06-16T13:10\" cite=\"mailto:Christian\"><\/ins><\/p>\n<p>Mathematisch gilt a \u00d7 a \/ a = a, also zum Beispiel 100 000 \u00d7 100 000 \/ 100 000 = 100 000. In Java ist das anders, da wir bei 100 000 \u00d7 100 000 einen \u00dcberlauf im int haben.<\/p>\n<p>System.out.println( 100000 * 100000 \/ 100000 );&#160;&#160;&#160;&#160; \/\/ 14100<\/p>\n<p>liefert daher 14100. Wenn wir den Datentyp auf long erh\u00f6hen, indem wir hinter ein 100 000 ein L setzen, sind wir bei dieser Multiplikation noch sicher, da ein long das Ergebnis aufnehmen kann.<\/p>\n<p>System.out.println( 100000L * 100000 \/ 100000 );&#160;&#160;&#160; \/\/ 100000<ins datetime=\"2012-06-16T13:10\" cite=\"mailto:Christian\"><\/ins><\/p>\n<p>Hinweis<\/p>\n<p>Ein Test auf \u00dcberlauf k\u00f6nnte 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.<\/p>\n<h6>\u00dcberlauf erkennen<\/h6>\n<p>F\u00fcr eine Operation wie die Addition oder Subtraktion l\u00e4sst sich relativ leicht erkennen, ob das Ergebnis \u00fcber das Ziel hinausschie\u00dft. Eine M\u00f6glichkeit 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 \u00fcber die Interna brauchen wir uns keine gro\u00dfen Gedanken machen, denn ab Java 8 kommen neue Methoden hinzu, die eine \u00dcberlauferkennung erm\u00f6glichen. Die Methoden gibt es in Math und StrictMath:<\/p>\n<p>\u00b7 static int addExact(int x, int y)<\/p>\n<p>\u00b7 static long addExact(long x, long y)<\/p>\n<p>\u00b7 static int subtractExact(int x, int y)<\/p>\n<p>\u00b7 static long subtractExact(long x, long y)<\/p>\n<p>\u00b7 static int multiplyExact(int x, int y)<\/p>\n<p>\u00b7 static long multiplyExact(long x, long y)<\/p>\n<p>\u00b7 static int toIntExact(long value)<\/p>\n<p>Alle Methoden werfen eine ArithmeticException, falls die Operation nicht durchf\u00fchrbar 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 \u201exxx overflow\u201c, auch wenn es eigentlich ein Unterlauf ist:<\/p>\n<p>System.out.println( subtractExact( Integer.MIN_VALUE, 1 ) ); \/\/ ArithmeticException<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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\u00e4\u00dfig nicht von Java angezeigt; weder der Compiler noch die Laufzeitumgebung [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11,66],"tags":[],"class_list":["post-1374","post","type-post","status-publish","format-standard","hentry","category-insel","category-java-8"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1374","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=1374"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1374\/revisions"}],"predecessor-version":[{"id":1375,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1374\/revisions\/1375"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=1374"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=1374"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=1374"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}