MODULE 3 · ARITHMETIC · 5/8

COMPUTE and operator precedence

15 min30 XPExercise

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:

  1. Multiply before you divide. 10 * 3 / 3 has no repeating decimal until the very end.
  2. 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.
  3. 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. 5 or 3.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

Check your understanding

1. What does COMPUTE WS-R = 2 + 3 * 4 ** 2 store?
2. WS-R is PIC 9(3)V99. Which statement stores exactly 10.00?
fixed format
Run your program to see its output here. The first visible test's input and datasets are used.
Submit to grade your program against every test.