Tipps & Tricks - Rundung und Casting von Zahlen

In diesem Beitrag erfahren Sie, wie Zahlenwerte speziell in Velocity, aber auch in Groovy, gerundet werden können. Für eine typsichere Weiterverarbeitung der Daten wird außerdem erklärt, wie Sie Variablen entsprechend casten können. Intrexx stellt für Rundungs- und Casting-Anforderungen über das $Math-Objekt unterstützende Methoden bereit.

Die dazugehörige Java-API-Dokumentation finden Sie hier.

Rundungsverfahren

Zum Runden von Zahlenwerten existiert eine Vielzahl an Verfahren. Im Folgenden sollen das kaufmännische und das mathematischen Runden etwas genauer beschrieben werden. Beide Rundungsverfahren werden von Intrexx unterstützt. Je nach Anwendungsfall bieten unsere Templates hierfür die passende Methode.

Kaufmännisches Runden

Die Regeln für kaufmännisches Runden sind wie folgt:

  • Ist die Ziffer an der ersten wegfallenden Dezimalstelle eine 0,1,2,3 oder 4, dann wird abgerundet

  • Ist die Ziffer an der ersten wegfallenden Dezimalstelle eine 5,6,7,8 oder 9, dann wird aufgerundet

  • Negative Zahlen werden anhand ihres Betrags gerundet, d.h. also ab der Zahl 5 weg von 0

Beispiel (Runden auf zwei Nachkommastellen):

12,3449 -> 12,34
12,3450 -> 12,35

-12,3449 -> -12,34
-12,3450 -> -12,35

Für das kaufmännische Runden stellt Intrexx die Methode "roundHalfAwayFromZero(double, precision)" und "roundHalfAwayFromZero(BigDecimal, precision)" zur Verfügung. Der zweite Parameter "precision" beschreibt hierbei die Anzahl der Nachkommastellen und ist optional.

Mathematisches Runden

Die Regeln für mathematisches Runden sind wie folgt:

  • Folgt auf die letzte beizubehaltende Ziffer eine 0, 1, 2, 3 oder 4, so wird abgerundet

  • Folgt auf die letzte beizubehaltende Ziffer eine 5, 6, 7, 8 oder eine 9, gefolgt von weiteren Ziffern, die nicht alle null sind, so wird aufgerundet

  • Folgt auf die letzte beizubehaltende Ziffer lediglich eine 5 (oder eine 5, auf die nur Nullen folgen), so wird derart gerundet, dass die letzte beizubehaltende Ziffer gerade wird

Beispiel (Runden auf eine Nachkommastelle):

1,2499 -> 1,2
1,2501 -> 1,3
1,2500 -> 1,2
1,3500 -> 1,4

Für das mathematische Runden stellt Intrexx die Methode "$Math.roundHalfEven()" zur Verfügung.

Unterschiede

Die Unterschiede zwischen den beiden vorgestellten Rundungsmethoden liegen in der "Verarbeitung" der Zahl 5, d.h. wenn eine Zahl zwischen zwei möglichen Rundungs-ergebnissen liegt. Beim kaufmännischen Runden kann lediglich der Fall vorkommen, dass um einen Wert von 0,5 aufgerundet wird. Das Abrunden von 0,5 kann zu keinem Zeitpunkt vorkommen. Dieser Fall ist dagegen beim mathematischen Runden berücksichtigt und sorgt dafür, dass beide Regeln gleichermaßen angewandt werden. Anwender müssen somit für jeden Anwendungsfall entscheiden, welches Rundungsverfahren hierfür rechnerisch, syntaktisch und logisch korrekt ist.

Methoden im Überblick

Wie eingangs erwähnt, stellt Intrexx in Velocity das Objekt "$Math" zur Verfügung, mit dem Rundungsoperationen durchgeführt werden können. Im Folgenden sollen einige Methoden einzeln vorgestellt werden.

roundHalfUp(double param)

Diese Methode rundet immer auf den nächsten Wert zum Übergabeparameter in positiver Richtung auf. Beispiel:

$Math.roundHalfUp(0.5)  == 1.0
$Math.roundHalfUp(-0.5) == 0.0

roundHalfAwayFromZero(double param)

Diese Methode rundet ähnlich wie roundHalfUp(), außer dass negative Werte immer von dem Wert Null weggerundet werden. Beispiel:

$Math.roundHalfAwayFromZero(0.5)  ==  1.0
$Math.roundHalfAwayFromZero(-0.5) == -1.0

roundHalfEven(double param)

Auch diese Methode rundet wie roundHalfUp(), jedoch werden Werte immer zum nächsten geraden Wert gerundet. Beispiel:

$Math.roundHalfEven(1.5)   ==  2.0
$Math.roundHalfEven(-1.5)  == -2.0
$Math.roundHalfEven(0.12)  ==  0.0
$Math.roundHalfEven(0.61)  ==  1.0
$Math.roundHalfEven(-0.61) == -1.0

Die beiden Methoden "roundHalfAwayFromZero()" und "roundHalfEven()" akzeptieren optional einen zweiten Übergabeparameter für die Rundungsgenauigkeit. Damit können Sie angeben, auf wie viele Stellen nach dem Komma gerundet werden soll. Negative Werte sind dabei auch möglich, um die Genauigkeit vor dem Komma zu beeinflussen.

Typsichere Weiterverarbeitung

Hin und wieder ist es erforderlich, dass die Zahlen einem bestimmten Typ entsprechen müssen. Auch hierfür haben Sie einige Möglichkeiten zur Verfügung. Im Rahmen des Rundens stehen für die oben genannten Methoden auch die entsprechenden Pendants zur Verfügung, um die gerundeten Werte in einem bestimmten Datentyp zurückgeliefert zu bekommen. Im Beispiel sieht der Aufruf dann wie folgt aus:

$Math.roundHalfUpAsInt(double)
$Math.roundHalfUpAsLong(double)

Selbstverständlich gibt es auch universelle Cast-Methoden, die vom $Math-Objekt bereit-gestellt werden. Hierzu zählen:

$Math.toInteger(java.lang.Object p_value)
$Math.toLong(java.lang.Object p_value)
$Math.toFloat(java.lang.Object p_value)
$Math.toDouble(java.lang.Object p_value)
$Math.toBigDecimal(java.lang.Object p_value)

Jede dieser Methoden akzeptiert einen Übergabeparameter vom Typ java.lang.Object, somit können unter anderem auch Zeichenketten (Strings) übergeben und umgewandelt werden. Im Falle von Zeichenketten dürfen jedoch keinerlei Trennzeichen wie Tausendertrennzeichen oder Dezimaltrenner enthalten sein. Optional können Sie auch immer einen Fallback-Wert des entsprechenden Typs mitgeben. Falls eine Umwandlung nicht funktionieren sollte, wird dieser Fallback-Wert zurückgegeben. Ebenfalls abgefangen werden beim Casten mit Hilfe dieser Methoden eventuelle auftretende Bereichsüberlaufe.

Verwendung in Groovy

Die aufgeführten Methoden "roundHalfAwayFromZero()" und "roundHalfEven()" sind im Groovy-Umfeld ebenfalls aufrufbar. Importieren Sie dazu die Klasse "de.uplanet.util.math.RoundingUtil" in Ihr Skript. Zum typsicheren Arbeiten und Casten stehen in Groovy keine speziellen Methoden zur Verfügung, da in diesem Fall auf die Groovy-eigenen Methoden zurückgegriffen werden kann.