This blog article is about the use of decimal places also known as Arithmetic Precision, in Oracle Application Composer.
Arithmetic precision in Oracle Fusion Applications relates to the number of decimal places displayed and stored in numeric fields. For example, distance measured in kilometers can be displayed and stored with three decimal places to show distance to the nearest metre: 300.124km is 300,124 metres.
When a new record is created, values with a greater number of decimal places that are entered are rounded off to the allowed number of decimal places predefined in the field at the time the record is saved.
For example if a new distance of 478,525.124245 is input into the distance field described above, the value stored would be 478,525.124 as the input value would be rounded down.
Here is a screen shot of the Edit screen of a field called Distance highlighting where the number of decimal places is configured.
If a third of the distance needed to be automatically calculated and displayed, the value 478,525.124 would have to be divided by 3 and then could be displayed in a Text Field using Groovy script. The result below shows both the un-rounded and rounded result of dividing the above by 3.
1/3 of the distance = 159508.3746666667 1/3 of the distance (rounded) = 159508.375
Here is the code that displays the above:
// Retrieve the maximum number of decimal places for the Distance_c field def curObj = newView('myObject_c'); def attr = curObj.findAttributeDef("Distance_c"); def maxDecimalPlaces = attr.getScale(); // Divide the Distance value by three java.math.BigDecimal oldNum = Distance_c; def newDistance = Distance_c / 3; // Create a MathContext Object for rounding off values java.math.MathContext mc = new java.math.MathContext( newDistance.precision() - newDistance.scale() + maxDecimalPlaces, java.math.RoundingMode.HALF_DOWN); // Round off the new distance value def output = newDistance.round(mc); // Display new values rounded and not rounded def displayOutput = "1/3 of the distance = "+newDistance+ "\n" + "1/3 of the distance (rounded) = " + output; return displayOutput;
To retrieve the number of decimal places from the Distance field we have to retrieve the AttributeDef object by creating a handle to the ViewObject using the
newView Groovy function. The AttributeDef.getScale() method retrieves the value.
Distance_c value is divided by three and assigned to a variable using the
def keyword. Groovy automatically creates a
BigDecimal value which is why we didn't have to explicitly specify that. All numerical fields are BigDecimal values.
The MathContext class is the engine that performs the rounding in this example. The constructor that we used above to instantiate the MathContext is
MathContext(int setPrecision, RoundingMode setRoundingMode). The two parameters here define how rounding will be executed.
The first parameter
setPrecision is the number of digits to round to. The second parameter
setRoundingMode determines what rules to follow when rounding.
RoundingMode.HALF_DOWN rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case the value is round down. The RoundingMode javadoc contains more information on the different rounding modes.
The way that
newDistance.precision() - newDistance.scale() + maxDecimalPlaces is understood by looking at all three parameters and their place.
newDistance.precision() is the
BigDecimal.precision() function which returns the number of digits in the un-scaled value which is the total number of digits in the
newDistance value. In the example above this is 16.
newDistance.scale() is the
BigDecimal.scale() function which returns the number of digits to the right of the decimal point, which in the example above is 10.
By subtracting the
scale() value from the
precision() value we are able to retrieve the number of digits to the left of the decimal point which in this example is 6. Adding the
maxDecimalPlaces value of 3 makes a total of 9 which is the total number of digits that the newDistance needs to be rounded to -
Once the MathContext object is instantiated then the rounding operation is performed by executing the -
The code in the example after this point is for displaying the output. Incidentally when using the "\n" within the middle of a String in groovy will display in following line if the String is displayed in a multiline text box.
A note about the behavior of rounding and decimal places in currency fields is that it is different to normal numerical fields because it is dependent on the currency type not simply on the fact that it's a currency field. For example the number of maximum decimal places used in USD is 2 as opposed to the number of decimal places used in JPY is 0. This is because there is no smaller unit of currency than ¥1 unlike in USD. When entering a currency value into a currency field this will always result in the rounded value being stored based on the currency. However to retrieve the precision values in Groovy is not possible at present.