Topic: DMD0085 MATH - Calculate Expression | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Traditional math precedence (terms inside parentheses, then exponents and roots, then multiplication and division, and finally addition and subtraction) rules are used to solve the math expression, The use of parentheses to remove any ambiguity in the processing order is encouraged. Math Promotion/DemotionThe Do-more CPU is natively a 32-bit processor. Although many different data formats and sizes are supported, whenever an instruction must do a calculation with a PLC element, that PLC element's value usually gets promoted.
Whenever elements that are UNSIGNED BYTE, SIGNED BYTE, UNSIGNED WORD, SIGNED WORD are used in a mathematical calculation, they are processed natively as 32 bit signed integer. All of these data types easily fit and all of their values are supported as native 32 bit signed integers. Most mathematical calculations that take integers for their inputs will also return an integer. For example, when dividing two integers, the CPU performs integer division, not floating point division, meaning that integer 5 divided by integer 2 is integer 2, not the real value 2.5.
However, if a real value is ever part of a mathematical calculation, as soon as the real value is introduced into the calculation, the calculation starts performing floating point calculations, including promoting any intermediate integer values to their floating point equivalent. So (5 + 2) / 2.0 will calculate 5 + 2 as integer and the intermediate result will be integer 7. But when the integer 7 is divided by the floating point value 2.0, the CPU performs a floating point divide operation, resulting in a real value of 3.5.
The most common mistake occurs when dividing two integer values but the desired result is a fractional real result. Use the TOREAL() function to promote an integer value or integer expression to its real equivalent. For example, if you wanted to divide D10 by D11, and wanted a fractional floating point result, either of the following will give the desired result:
The thing to remember is that when a calculation involves both integer and floating point types, the integer types will be automatically promoted to floating point values so that the calculation can be performed using all floating point types. Floating point types are automatically truncated to integers when the program expects an integer value, for example, when a floating point variable is assigned to an integer variable.
All error conditions that arise while calculating an expression will be reported on the System Status page of the System Information dialog, and an appropriate system-level bit location ($IndexError, $OutOfRange, $Overflow, etc.) will be set ON. Math Execution SpeedInteger math is FAST, and Integer math is ACCURATE. Do-more controllers have 32 bits of integer accuracy, which is +/- 2 billion. If a million BYTE values of 255 are added together and the result (255,000,000 will fit in a 32-bit D location.
Floating point math is SLOWER (not SLOW, just SLOWER). It has 24 bits of ”accuracy” (7 bits for exponent, 1 bit for sign, for all 32 bits). For example, an attempt to add 1,000,000 (one million) to .0000001 (one millionth), will not result in 1,000,000.0000001, because a single REAL cannot hold THAT much accuracy in 32 bits. Real locations have the ability to store a large range of possible values within one 32 bit register, from very small to very large numbers (e.g. 0.0000001 and 1,000,000 or even 6.02x1023). There is a loss of accuracy, e.g. you cannot store EXACTLY 3.3, and you can’t add really large and really small numbers together and retain all of the accuracy of both numbers.
A single MATH box allows the programmer to freely mix REAL and integers, so the questions arise: when is accuracy lost? When is speed lost?
The Do-more controller will attempt to use integer math for all computations because it is fast and accurate. But when a REAL value is introduced, from that point forward, the remaining calculations will all be done in REAL. This is a bit of an oversimplification, because, when you have sub-expressions, each sub-expression obeys this rule, not just left-to-right at the ASCII expression level).
Here's an example: the calculation (CT0.Acc + CT1.Acc + CT2.Acc) / 3
is performed using all integer math. The calculation result is integer.
Integer division is one case where you do lose accuracy &endash; it TRUNCATES.
1 / 3 is 0.
If the alter the calculation to (CT0.Acc + CT1.Acc + CT2.Acc) / 3.0, Integer math is used on the on the 3 counter accumulators in the numerator (which is great for speed and accuracy), but the division is done with the REAL value 3.0, not the INTEGER value 3.
When the division is done with a REAL the calculation is performed as a floating point operation. This will produce the desired result as long as that result is stored in a REAL memory location.
What if the denominator is a non-REAL memory location, like V? For example: (CT0.Acc + CT1.Acc + CT2.Acc) / V10. Since V memory locations contain integer values, and the desired result is a REAL, the value in the V location must be converted to REAL value.
Note: Do not use casts, for example: Do not use V10:R. Casting is for reinterpreting the bit pattern, not for data conversions.
The MATH function called TOREAL() will perform the needed conversion. It takes the expression that is in parentheses and converts it TO REAL. If the expression is already a REAL value, it doesn’t do anything. If the expression is an integer, it converts it to a REAL.
If V10 contains the integer value 3 then (CT0.Acc + CT1.Acc + CT2.Acc) / TOREAL(V10) would generate the desired result.
Alternatively, TOREAL(CT0.Acc + CT1.Acc + CT2.Acc) / V10 would give the same result, but floating point calculations would be performed for the entire calculation instead of just the division.
The rule of thumb is to do integer math as long as possible when you know you will not lose accuracy. Addition and subtraction are always good for INTEGER. Multiplication and division is usually good with integer, but multiplying two large 32 bit numbers that will exceed 32 bits won’t work, the multiplication must be done as REAL. Division is good with integer when decimal point accuracy is not needed.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameters:Note: Use the F9 key (Element Browser) or Down-Arrow key (Auto-Complete) at any time to see a complete list memory locations that are valid in the current field of the instruction.
Result - designates a location to store the result of the math computation. This can be any writable numeric location.
Expression - contains the memory locations, mathematical operators, and/or math functions from the following tables that make up the formula to calculate. This can be any valid combination of constant values, bit or numeric memory locations, math operators, nested parentheses, and math functions up to a maximum of 1024 characters. Expressions can be nested up to 8 levels deep and chained between operators within function parameters, and as array indices, so use of parentheses is recommended to ensure proper evaluation order.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Rung Example:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|