Numeric Operations
Numbers may be stored internally in several different ways, which can have a noticeable effect on the performance of operations requiring numeric parameters. These are:
-
A string type that is a valid number. If referenced when a numeric is required, it has to be parsed to check that it is a valid number and converted to a numeric type.
-
A binary number which can usually be used directly when a numeric is required and is therefore the most efficient.
-
A string number that causes any calculation to be performed using string number math routines. These are many times slower than their binary equivalents.
Binary numbers are stored together with a scale value. This scale value can range from zero to the maximum scaling factor, or precision, in force when the number is generated. Precision is dynamic and can be changed at any point in the program (via the PRECISION statement). The scale value of a variable is more difficult to predict than previous releases. However, in general, numbers are less likely to overflow as the scale value is only as high as is required to hold the number.
The scale value of the result of a calculation depends both on the scale values of the operands and the type of operation:
-
Add and Subtract generate a result that has a scale value that is the maximum of the scale values of the operands (regardless of the current precision).
-
Multiply generates a result that has a scale value that is the addition of the scale values of the operands, unless this is greater than the current precision, in which case the number is scaled down to the current precision.
-
Divide generates a result that has a scale dependent on the number of decimal places of the result, with a maximum scale value of the current precision.
-
Trigonometric and Logarithmic functions calculate at a fixed precision of 5. If this is larger than the current precision, the result is scaled down to the current precision.
Operations that require integer parameters are able to use numbers with a zero scale value directly, but numbers with a non-zero scale factor have to be unscaled first. It is therefore preferable in this case to avoid operations that generate numbers with decimal places.
Note
-
Literals and constants with decimal places are not truncated to the current PRECISION, so a formula may contain values to a greater accuracy than the final result.
-
Assignment is not affected by PRECISION, so
VAR2=VAR1
assigns the exact value ofVAR1
toVAR2
even if it has a scale factor larger than the current PRECISION. -
The PRECISION can be dynamically changed while a program is running. Changing the PRECISION only affects the results of subsequent calculations.
-
Programs and CALLed subroutines need not have the same PRECISION. A RETURN causes the PRECISION to be reset to its value at the CALL.
If the value of a binary number, or the result of binary arithmetic, is of a magnitude that cannot be stored in 48 bit two's complement binary (approximately 14 decimal digits), it is converted to a string number and calculations are performed using string number math routines. If the final result of an operation performed using string number math routines can be stored in 48 bit two's complement binary within the limits of the current precision, it is converted and stored as binary.
Considerations for Efficiency
-
Always use the simplest operators (
X=X+X
instead ofX=X*2
,X=X*X
instead ofX=X^2
, and so on). -
If an arithmetic expression is used more than once, assign it to a variable and use this variable in place of the expression so that it only has to be evaluated once. For example, in
FOR I=1 TO
x, where x is an expression or non-integer descriptor, assign x to a variable and substitute it for x. This is especially important if the expression is complicated, may have to convert operands to the correct type, or contains functions. -
Complex expressions evaluate faster than less complex expressions with intermediate results. (Use
HYPOTENUSE=SQRT(A*A+B*B)
instead ofQ=A*A; R=B*B; S=Q+R; HYPOTENUSE=SQRT(S))
. -
If using variables containing constants, use EQUATE rather than assignment statements.
Note
Constant values are compiled into literals in the object code every time they are used; assigning to a variable only compiles the literal where it is assigned. Therefore using EQUATE increases object code size.