Language basics / Data types |
The DECIMAL data type is provided to handle large numeric values with exact decimal storage.
DECIMAL [ ( precision[,scale]) ]
Use the DECIMAL data type when you need to store values that have fixed number of digits on the right and left of the decimal point (DECIMAL(p,s)), or to store a floating point decimal with an exact number of significant digits (DECIMAL(p)).
DEC, DECIMAL and NUMERIC are synonyms.
DECIMAL variables are initialized to NULL in functions, modules and globals.
When using DECIMAL(p,s) with a precision and scale, you define a decimal for fixed point arithmetic, with p significant digits and s digits on the right of the decimal point. For example, DECIMAL(8,2) can hold the value 123456.78 (8 (p) = 6 digits on the left + 2 (s) digits of the right of the decimal point).
When using DECIMAL without a precision and scale, it defaults to DECIMAL(16), a floating-point number with a precision of 16 digits.
MAIN DEFINE d1 DECIMAL(10,4) DEFINE d2 DECIMAL(10,3) LET d1 = 1234.4567 LET d2 = d1 / 3 -- Rounds decimals to 3 digits DISPLAY d1, d2 END MAIN
DECIMAL values can be converted to strings according to the DBFORMAT (or DBMONEY) environment variable (defines the decimal separator).
The largest absolute value that a DECIMAL(p,s) can store without errors is 10p-s - 10s. The stored value can have up to 30 significant decimal digits in its fractional part, or up to 32 digits to the left of the decimal point.
When using DECIMAL(p,s) the range of values is defined by the p, the number of significant digits. For example, a variable defined as DECIMAL(5,3) can store values in the range -99.999 to 99.999. The smallest positive non zero value is 0.001.
When using DECIMAL(p) the magnitude can range from -N*10-124 to N*10124, where N can have up to p significant digits and be 0<N<10. For example, a variable defined as DECIMAL(5) can store values in the range -9.9999e-124 to 9.9999e+124. The smallest positive non zero value is 9.9999e-130.
When the default exception handler is used, if you try to assign a value larger than the decimal definition (for example, 12345.45 into DECIMAL(4,2) ), no out of range error occurs, and the variable is assigned with NULL. If WHENEVER ANY ERROR is used, it raises error -1226. If you do not use WHENEVER ANY ERROR, the STATUS variable is not set to -1226.
Data type conversion can be controlled by catching the runtime exceptions. For more details, see Handling type conversion errors.
When computing or converting decimal values, the "round half away from zero" rule will apply: If the fraction of the value v is exactly 0.5, then r = v + 0.5 if v is positive, and r = v - 0.5 if v is negative. For example, when the result must be rounded to a whole number, 23.5 gets rounded to 24, and -23.5 gets rounded to -24.
In the next example, the division result of 11 / 3 gives the infinite decimal value 3.666666... (with an infinite decimal part). However, this value cannot be stored in a fixed point decimal type. When stored in a DECIMAL(10,2), the value will be rounded to 3.67, and when multiplying 3.67 by 3, the result will be 11.01, instead of 11:
MAIN DEFINE v DECIMAL(10,2) LET v = 11 / 3 DISPLAY "1. v = ", v USING "---&.&&&&&&&&" LET v = v * 3 DISPLAY "2. v = ", v USING "---&.&&&&&&&&" END MAIN
1. v = 3.67000000 2. v = 11.01000000
A couple of precision math functions are available, to be used with DECIMAL values. These functions have a higher precision as the standard C library functions based on C double data type, which is equivalent to FLOAT: