Tips & Tricks - 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.

  • 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):

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.