Thursday, November 11, 2010

the noOfDecimals property

The noOfDecimals property caused some sensation over the last couple of weeks on the projects we're working on. A little diggin' resulted in this post:

The noOfDecimals property can be set on an EDT of type real and (overridden) on a form/reportRealControl. The help on the noOfDecimals property tells us 'number of decimals displayed'.

Does this mean it only shows a rounded value when being displayed and is the actual value stored in the DB much more precise?
Or does it actually round off and is the rounded value also what's in the DB?

Well … both are true. Kind of anyway … check out the example below.

First of all, I've set the noOfDecimals to 4 on the SalesPrice EDT.
Then I created a 3 custom of EDT's (noOfDecimals = 0, 2 and  4, all extending EDT 'price'), a table and a form.

A little explanation on how the form works:
- The 'auto calc fields' checkbox indicates whether the fields in between 'quantity' and 'code calculated' are calculated in code on insert/update based on the sales price and the quantity (salesprice * quantity).
- In the third record, I have manually entered '10/3' on all fields, which is translated to 3.33333… by Ax
- For the two columns to the left of the 'code calculated' columns, the noOfDecimals property is overridden on the realFormControl :
- EDT set to 4, formcontrol set to 2
- ETD set to 2, formcontrol set to 4
- The last column shows a value (hardcoded in insert/update of the table) of 0.12345678901234567890, but with noOfDecimals set to zero for the table field.

The result looks like this:

It really does seem like the noOfDecimals property does what's to be expected: values are rounded to the number of decimals as set up on the EDT or form control.

Let's have a look in the DB:

- Only the record where autoCalc = false match the values as shown in the Ax form.
- The first two records completely ignore the noOfDecimals property.

Values that are calculated in X++ code are stored in the DB with precision of 12 decimals. All fields of type real are defined in SQL as 'numeric(28,12)' where 12 is the number of decimal places (and 16 places are left for the integer value).
Values that are entered on the form are rounded based on the noOfDecimals property.

Have a look at the values recorded during debugging of the update-event on the table:

All variables of base type real - regardless of the EDT and the noOfDecimals - in X++ code are treated as a 'real' with a precision of 16 decimals. Once written to the DB they are rounded to 12 decimals.
I don't get why my 10/3 has a precision of 15 decimals, while the hardcoded value goes up to 16 decimal places ...

Anyway, the statement 'number of decimals displayed' is correct … but you can't be sure if the value in the DB is more precise or not.

Or can you? Almost all calculations go through logic (mostly static methods on the currency table) applying rounding set up in the company parameters, currency parameters, tax codes, … so yes, actually you can.

Also see if you're thinking about changing the number of decimals throughout Ax.

Another thing I noticed: whatever numeric value you pass to infolog or print, only 2 decimals are shown (rounded off).

Download the Ax EDT's, table and form I used above here.