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

You can find the corresponding Java API documentation 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 decimal place is 0, 1, 2, 3 or 4, it is rounded down

  • If the digit in the first decimal place is a 5, 6, 7, 8 or 9, it is rounded up

  • Negative numbers are rounded according to their amount, i.e. from the number 5 away from 0

Example (rounding to one decimal place):

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" describes 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, it is rounded down

  • If the last digit to be retained is followed by a 5, 6, 7, 8 or a 9, followed by further digits that are not all zero, 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 last digit to be retained is rounded so that it 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 provides the method "$Math.roundHalfEven()".

Differences

The differences between the two rounding methods presented lie in the "processing" of the number 5, i.e. when a number lies between two possible rounding results. 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 at the beginning, Intrexx provides the "$Math" object in Velocity, which can be used to perform rounding operations. 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()" optionally accept a second transfer parameter for 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 conversion does not work, this fallback value is returned. Any overflows that may occur in casting can also be captured with the help of these methods.

Use in Groovy

The listed methods "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. 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.