Advanced Techniques - Rounding and casting of numbers
In this workshop you will learn how numerical values can be rounded,
in particular in Velocity, but also in Groovy. To ensure type-safe further
processing of the data, the corresponding casting of variables will also be
explained. Intrexx provides supporting techniques for rounding and casting
requirements with the $Math object. The corresponding Java API documentation
can be found
here.
Rounding procedure
There is a variety of methods for rounding numerical values. In the following,
the business and mathematical rounding methods are described in detail.
Both of these rounding methods are supported by Intrexx.
Depending on the particular application, our templates provide the appropriate
method.
Business rounding
The rules for business rounding (also known as round half away from zero)
are as follows:
- If the digit in the first removed decimal place is a 0, 1, 2, 3 or 4,
then the value will be rounded down.
- If the digit in the first removed decimal place is a 5, 6, 7, 8 or 9,
then the value will be rounded up.
- Negative numbers are rounded according to their amount, i.e. from the
number 5 away from zero.
Example (Rounding to two decimal places):
12,3449 -> 12,34
12,3450 -> 12,35
-12,3449 -> -12,34
-12,3450 -> -12,35
For business rounding, Intrexx provides the method
"roundHalfAwayFromZero(double, precision)" and "roundHalfAwayFromZero(BigDecimal, precision)".
The second parameter "precision" defines the number of decimal
places and is optional.
Mathematical rounding
The rules for mathematical rounding (also known as round half to even) are as follows:
-
If the last digit to be retained is followed by a 0, 1, 2, 3 or 4,
the value will be rounded down.
-
If the last digit to be retained is followed by a 5, 6, 7, 8 or 9,
followed by further digits which are not all zero, then the value
will be rounded up.
-
If the last digit to be retained is followed by a 5 alone
(or a 5 with only zeroes following), then the rounding is such that the
last retained digit is even.
Example (rounding to one decimal place):
1,2499 -> 1,2
1,2501 -> 1,3
1,2500 -> 1,2
1,3500 -> 1,4
For mathematical rounding, Intrexx offers you the "$Math.roundHalfEven()" method.
Differences
The differences between the two rounding methods lie in the handling of the
number 5, i.e. when a number is between two possible outcomes of the
rounding process. With business rounding, it is only possible for a value of
0.5 to be rounded up. 0.5 will never be rounded down with this method.
This situation is taken into account by the mathematical rounding method,
which ensures that both rules are applied equally.
Users must therefore decide for each individual case, which rounding procedure
is computationally, syntactically and logically correct.
The methods in overview
As mentioned previously, Intrexx provides the $Math object in Velocity that
rounding operations can be performed with. In the following, some of the methods
will be presented one after the other.
roundHalfUp(double param)
This method always rounds to the nearest value to the transfer parameter
in the positive direction.
Example:
$Math.roundHalfUp(0.5) == 1.0
$Math.roundHalfUp(-0.5) == 0.0
roundHalfAwayFromZero(double param)
This method rounds similarly to roundHalfUp(), except that negative values
are always rounded away from the value zero.
Example:
$Math.roundHalfAwayFromZero(0.5) == 1.0
$Math.roundHalfAwayFromZero(-0.5) == -1.0
roundHalfEven(double param)
This method also rounds similarly to roundHalfUp(), but values are always
rounded to the nearest even value.
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() accept
an optional second transfer parameter to specify the rounding accuracy.
Here you can specify the number of decimal places that the value should be
rounded to. Negative values can also be applied, to influence the accuracy
before the decimal point.
Type-safe further processing
Occasionally it is necessary that the numbers correspond to a specific type.
Several options are also available to you here. In the scope of rounding,
the corresponding counterparts for the above methods are available, so that
the rounded values can be returned in a specific data type.
For the examples given, the calls look like this:
$Math.roundHalfUpAsInt(double)
$Math.roundHalfUpAsLong(double)
Naturally, 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 transfer parameter of the java.lang.Object
type, so that (among others) character strings can also be transferred and
transformed. However, in the case of strings, no delimiters such as
thousand separators, or decimal separators, can be included.
You also always have the option to specify a fallback value of the
appropriate type. If a transformation fails, this fallback value will be
returned. Any overflows that may occur in casting can also be
captured with the help of these methods.
Use in Groovy
The "roundHalfAwayFromZero()" and "roundHalfEven()" methods described can
also be called in the Groovy environment. Import the de.uplanet.util.math.RoundingUtil
class into your script. For type-safe work and casting there are no special
methods available in Groovy, since the native Groovy methods can be used
in this case.