Tips & Tricks - Rounding and Casting Numbers
In this post, you'll learn how to round numerical values specifically in Velocity, as well as in Groovy. To ensure that the data is processed with the correct data types, this section also explains how to cast variables accordingly. Intrexx provides methods via the $Math object to support rounding and casting requirements.
You can find the corresponding Java API documentation here.
Circular Procedure
There are a variety of methods for rounding numerical values. The following sections will describe commercial and mathematical rounding in more detail. Intrexx supports both round-robin methods. Depending on the use case, our templates offer the appropriate method for this.
Commercial Rounding
The rules for rounding in business are as follows:
-
If the digit at the first decimal place to be omitted is 0, 1, 2, 3, or 4, the number is rounded down
-
If the digit at the first decimal place to be dropped is a 5, 6, 7, 8, or 9, then the number is rounded up
-
Negative numbers are rounded based on their absolute value; that is, starting with the number 5, they are rounded away from 0.
Example (round to two decimal places):
12.3449 -> 12.34
12.3450 -> 12.35
-12.3449 -> -12.34
-12.3450 -> -12.35
For commercial rounding, Intrexx provides the methods "roundHalfAwayFromZero(double, precision)" and "roundHalfAwayFromZero(BigDecimal, precision)." The second parameter, "precision," specifies the number of decimal places and is optional.
Mathematical Rounding
The rules for mathematical rounding are as follows:
-
If the last digit to be retained is followed by a 0, 1, 2, 3, or 4, the number is rounded down
-
If the last digit to be retained is followed by a 5, 6, 7, 8, or 9, followed by additional digits that are not all zeros, the number is rounded up.
-
If the last digit to be retained is followed only by a 5 (or a 5 followed only by zeros), the number is rounded so that the last digit to be retained is even.
Example (round to one decimal place):
1.2499 -> 1.2
1.2501 -> 1.3
1.2500 -> 1.2
1.3500 -> 1.4
For mathematical rounding, Intrexx provides the "$Math.roundHalfEven()" method.
Differences
The differences between the two rounding methods described lie in how the number 5 is "handled," that is, when a number falls between two possible rounded values. In commercial rounding, the only situation that can occur is rounding up by 0.5. Rounding down from 0.5 cannot occur at any time. In contrast, this case is taken into account in mathematical rounding and ensures that both rules are applied equally. Users must therefore decide, for each specific case, which rounding method is mathematically, syntactically, and logically correct.
Overview of Methods
As mentioned at the beginning, Intrexx provides the "$Math" object in Velocity, which can be used to perform rounding operations. In the following, we will present several methods individually.
roundHalfUp(double param)
This method always rounds up to the next value in the positive direction relative to the passed parameter. Example:
$Math.roundHalfUp(0.5) == 1.0
$Math.roundHalfUp(-0.5) == 0.0
roundHalfAwayFromZero(double param)
This method rounds in a similar way to roundHalfUp(), except that negative values are always rounded away from zero. Example:
$Math.roundHalfAwayFromZero(0.5) == 1.0
$Math.roundHalfAwayFromZero(-0.5) == -1.0
roundHalfEven(double param)
Like roundHalfUp(), this method also rounds, but values are always rounded to the nearest even number. Example:
$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
The two methods, "roundHalfAwayFromZero()" and "roundHalfEven()", optionally accept a second parameter to specify the rounding precision. This allows you to specify the number of decimal places to which the number should be rounded. Negative values are also possible in order to adjust the precision to the left of the decimal point.
Type-Safe Post-Processing
From time to time, it is necessary for the numbers to conform to a specific type. You have several options available for this as well. As part of the rounding process, corresponding functions are also available for the methods listed above to return the rounded values in a specific data type. In the example, the call looks like this:
$Math.roundHalfUpAsInt(double)
$Math.roundHalfUpAsLong(double)
Of course, there are also universal cast methods provided by the $Math object. These include:
$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)
Each of these methods accepts a parameter of type `java.lang.Object`, which means that, among other things, strings can also be passed and converted. However, strings must not contain any separators, such as thousands separators or decimal separators. Optionally, you can always specify a fallback value of the corresponding type. If a conversion fails, this fallback value is returned. These methods also catch any range overflows that may occur during casting.
Usage in Groovy
The methods listed here, "roundHalfAwayFromZero()" and "roundHalfEven()", can also be called in the Groovy environment. To do this, import the "de.uplanet.util.math.RoundingUtil" class into your script. Groovy does not provide any special methods for type-safe operations and casting, since Groovy's built-in methods can be used for this purpose.