COMPUTE and operator precedence
The arithmetic verbs are clear for one operation, but a formula like
compound interest would take five statements. COMPUTE lets you write the
formula directly:
COMPUTE WS-AMOUNT ROUNDED =
WS-PRINCIPAL * (1 + WS-RATE / 100) ** WS-YEARS
ON SIZE ERROR DISPLAY "AMOUNT TOO LARGE"
END-COMPUTE
The result goes into the field on the left of =. ROUNDED, ON SIZE
ERROR and NOT ON SIZE ERROR work exactly as they do on the verbs.
Operators and precedence
| Priority | Operator | Meaning |
|---|---|---|
| 1 | + - (unary) |
sign, as in -WS-X |
| 2 | ** |
exponentiation |
| 3 | * / |
multiply, divide |
| 4 | + - |
add, subtract |
Operators of equal priority run left to right, and parentheses override
everything. Put spaces around every operator: WS-A-WS-B is read as one
data name with hyphens, not a subtraction.
IDENTIFICATION DIVISION.
PROGRAM-ID. PRECEDE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-R PIC S9(5)V99.
01 WS-D PIC 9V9(4).
PROCEDURE DIVISION.
COMPUTE WS-R = 2 + 3 * 4
DISPLAY "2 + 3 * 4 = " WS-R
COMPUTE WS-R = (2 + 3) * 4
DISPLAY "(2 + 3) * 4 = " WS-R
COMPUTE WS-R = 10 / 3 * 3
DISPLAY "10 / 3 * 3 = " WS-R
COMPUTE WS-R = 10 * 3 / 3
DISPLAY "10 * 3 / 3 = " WS-R
COMPUTE WS-D = 1 / 3
COMPUTE WS-R = WS-D * 3
DISPLAY "STEP BY STEP = " WS-R
STOP RUN.
Output:
2 + 3 * 4 = +00014.00
(2 + 3) * 4 = +00020.00
10 / 3 * 3 = +00009.99
10 * 3 / 3 = +00010.00
STEP BY STEP = +00000.99
The intermediate precision trap
Mathematically, 10 / 3 * 3 is 10. In COBOL it's 9.99. The division
produces 3.333… — a repeating decimal that must be cut off at some number
of places — and multiplying the cut-off value by 3 can never get back to 10.
The compiler decides how many decimal places intermediate results keep, using rules based on the pictures of the operands and the target (IBM documents them under "intermediate results"). You can't see those intermediate fields, so the safe habits are:
- Multiply before you divide.
10 * 3 / 3has no repeating decimal until the very end. - Don't split a formula into steps with narrow work fields. The last example stores 1/3 in a four-decimal field (0.3333), and 0.3333 × 3 is 0.9999, truncated to 0.99. If you must use work fields, give them more decimals than the final answer.
- Round only the final result with
ROUNDED.
Exponents and huge numbers
** with a fractional base (like 1.0425 ** 30) is computed with
limited precision. For typical loan and savings amounts the result is
exact to the cent, but for very large values or long terms, check
results against a known-good figure before trusting them.
On the job
Most modern shops prefer COMPUTE for anything beyond a single add or
subtract, because the formula can be compared line-by-line with the
business spec. You'll still maintain plenty of verb-style code, so read
both fluently.
Your task
Write a compound interest calculator. Read, one per line:
- the principal (e.g.
1000.00) - the annual interest rate in percent (e.g.
5or3.75) - the number of years (whole number)
Interest is compounded once a year:
amount = principal × (1 + rate ÷ 100) ^ years
Use a single COMPUTE ... ROUNDED for the final amount (rounded to the
cent), then work out the interest earned (amount − principal). For
1000.00, 5, 5 the output is:
FINAL AMOUNT: 1,276.28
INTEREST: 276.28