COBOLMainframe

COBOL Arithmetic: ADD, SUBTRACT, MULTIPLY, DIVIDE, and COMPUTE

TT
TopicTrick
COBOL Arithmetic: ADD, SUBTRACT, MULTIPLY, DIVIDE, and COMPUTE

COBOL provides five arithmetic verbs — ADD, SUBTRACT, MULTIPLY, DIVIDE, and COMPUTE — plus the ROUNDED and SIZE ERROR options that make financial calculations precise and safe. Understanding how these work, when to use each, and how to protect against overflow is essential for any mainframe developer.

Why COBOL Arithmetic is Different

In most languages, arithmetic is implicit: x = y + z. COBOL uses explicit verbs that read like instructions: ADD Y TO Z GIVING X. This verbosity has a purpose: COBOL arithmetic operates on decimal fields (PIC 9, COMP-3), not binary floats, making it exact for financial calculations. There is no floating-point rounding error in COMPUTE INTEREST = BALANCE * RATE.

ADD

ADD has three forms depending on where the result goes.

ADD ... TO (result in the last operand)

cobol
ADD 1 TO WS-COUNTER.
ADD WS-AMOUNT TO WS-TOTAL.
ADD WS-TAX TO WS-SURCHARGE TO WS-TOTAL.    *> adds both to WS-TOTAL

The last operand receives the accumulated result. In the third example, both WS-TAX and WS-SURCHARGE are added to WS-TOTAL — they are not added together first.

ADD ... TO ... GIVING (result in a separate field)

cobol
ADD WS-SUBTOTAL TO WS-TAX GIVING WS-INVOICE-TOTAL.
ADD WS-HOURS WORKED TO WS-OVERTIME GIVING WS-TOTAL-HOURS.

The source operands are unchanged; only the GIVING field is updated. This is the safe form when you want to preserve the input values.

ADD CORRESPONDING (field-by-field within matching records)

cobol
01 WS-DAILY-TOTALS.
   05 DT-SALES      PIC S9(9)V99 COMP-3.
   05 DT-RETURNS    PIC S9(9)V99 COMP-3.
   05 DT-NET        PIC S9(9)V99 COMP-3.

01 WS-MONTHLY-TOTALS.
   05 MT-SALES      PIC S9(11)V99 COMP-3.
   05 MT-RETURNS    PIC S9(11)V99 COMP-3.
   05 MT-NET        PIC S9(11)V99 COMP-3.

ADD CORRESPONDING WS-DAILY-TOTALS TO WS-MONTHLY-TOTALS.

CORRESPONDING matches fields by name and adds them pairwise. Only matching names are added; unmatched fields are ignored. This is elegant for accumulating structured totals but requires consistent naming conventions.

SUBTRACT

SUBTRACT ... FROM

cobol
SUBTRACT WS-DISCOUNT FROM WS-PRICE.
SUBTRACT WS-TAX FROM WS-REFUND FROM WS-NET.    *> subtracts both

SUBTRACT ... FROM ... GIVING

cobol
SUBTRACT WS-DEDUCTIONS FROM WS-GROSS-PAY GIVING WS-NET-PAY.
SUBTRACT 100 FROM WS-BALANCE GIVING WS-NEW-BALANCE.

SUBTRACT CORRESPONDING

cobol
SUBTRACT CORRESPONDING WS-ADJUSTMENTS FROM WS-BALANCES.

Subtracts matching fields pairwise, analogous to ADD CORRESPONDING.

MULTIPLY

MULTIPLY ... BY (result in last operand)

cobol
MULTIPLY WS-QUANTITY BY WS-UNIT-PRICE.   *> WS-UNIT-PRICE = QTY * PRICE
MULTIPLY 1.08 BY WS-SUBTOTAL.            *> add 8% tax in place

MULTIPLY ... BY ... GIVING

cobol
MULTIPLY WS-HOURS BY WS-RATE GIVING WS-EARNINGS.
MULTIPLY WS-PRINCIPAL BY WS-RATE GIVING WS-INTEREST-AMT.

The GIVING form is almost always preferable — it preserves both source fields and makes the intent clear.

DIVIDE

DIVIDE has the most variants because division can produce both a quotient and a remainder.

DIVIDE ... INTO (result in last operand)

cobol
DIVIDE 12 INTO WS-ANNUAL-AMOUNT.          *> monthly amount in place
DIVIDE WS-TOTAL-ITEMS INTO WS-TOTAL-COST. *> average cost in place

DIVIDE ... INTO ... GIVING

cobol
DIVIDE 12 INTO WS-ANNUAL-SALARY GIVING WS-MONTHLY-SALARY.
DIVIDE WS-DIVISOR INTO WS-DIVIDEND GIVING WS-QUOTIENT.

DIVIDE ... BY ... GIVING

The BY form reverses the operand order and is often more readable:

cobol
DIVIDE WS-DIVIDEND BY WS-DIVISOR GIVING WS-QUOTIENT.
DIVIDE WS-ANNUAL-FEE BY 12 GIVING WS-MONTHLY-FEE.

DIVIDE with REMAINDER

cobol
DIVIDE WS-TOTAL-DAYS BY 7
    GIVING WS-WHOLE-WEEKS
    REMAINDER WS-REMAINING-DAYS.

The REMAINDER clause captures the modulus — the fractional part is discarded from GIVING and the true integer remainder goes to REMAINDER.

COMPUTE

COMPUTE evaluates arithmetic expressions using standard infix notation with operator precedence. It is the closest COBOL comes to conventional algebraic notation:

cobol
COMPUTE WS-RESULT = WS-A + WS-B * WS-C.
COMPUTE WS-AREA = WS-LENGTH * WS-WIDTH.
COMPUTE WS-FUTURE-VALUE = WS-PRINCIPAL * (1 + WS-RATE) ** WS-PERIODS.
COMPUTE WS-MONTHLY-PAYMENT ROUNDED =
    (WS-LOAN-AMOUNT * WS-MONTHLY-RATE) /
    (1 - (1 + WS-MONTHLY-RATE) ** (-WS-TERM-MONTHS)).

COMPUTE Operators

OperatorMeaning
+Addition
-Subtraction
*Multiplication
/Division
**Exponentiation

Precedence: parentheses → exponentiation → multiplication/division (left to right) → addition/subtraction (left to right).

When to Use COMPUTE

Use COMPUTE for compound expressions, exponentiation (the only way to do it in one statement), and cases where the full formula is clearer as an expression. Use individual verbs when the semantic is simple and the verb name adds clarity:

cobol
*> Clear — use ADD:
ADD 1 TO WS-RECORD-COUNT.

*> Complex formula — use COMPUTE:
COMPUTE WS-NPV =
    WS-CASH-FLOW-1 / (1 + WS-DISCOUNT-RATE) ** 1 +
    WS-CASH-FLOW-2 / (1 + WS-DISCOUNT-RATE) ** 2 +
    WS-CASH-FLOW-3 / (1 + WS-DISCOUNT-RATE) ** 3.

ROUNDED

Without ROUNDED, arithmetic results are truncated to the precision of the receiving field. With ROUNDED, the last kept digit is adjusted up if the first dropped digit is 5 or more:

cobol
01 WS-AMOUNT     PIC S9(9)V99 COMP-3.
01 WS-RATE       PIC V9(6) COMP-3 VALUE .065000.
01 WS-INTEREST   PIC S9(9)V99 COMP-3.

COMPUTE WS-INTEREST ROUNDED =
    WS-AMOUNT * WS-RATE.

If WS-AMOUNT = 1000.00 and WS-RATE = .065000, the exact result is 65.000000. With two decimal places in the receiving field: truncated = 65.00 (correct here), but at 1000.005 * .065000 = 65.00325 — truncated = 65.00, rounded = 65.00 (rounds to same). At 1000.008 * .065000 = 65.00052 — rounded stays 65.00. The difference matters at scale: accumulated rounding errors in millions of transactions can create significant discrepancies in reconciliation.

ROUNDED can be applied to multiple receiving fields in one statement:

cobol
ADD WS-INTEREST TO WS-BALANCE ROUNDED.
COMPUTE WS-TOTAL ROUNDED
        WS-PER-UNIT ROUNDED = WS-GRAND-TOTAL / WS-ITEM-COUNT.

ON SIZE ERROR

ON SIZE ERROR detects arithmetic overflow — the result exceeds the capacity of the receiving field:

cobol
COMPUTE WS-RESULT = WS-LARGE-A * WS-LARGE-B
    ON SIZE ERROR
        MOVE 'OVERFLOW' TO WS-ERROR-MESSAGE
        SET WS-ERROR-FOUND TO TRUE
        PERFORM LOG-ERROR
    NOT ON SIZE ERROR
        PERFORM PROCESS-VALID-RESULT
END-COMPUTE.

When SIZE ERROR triggers:

  • The receiving field is NOT updated (the old value is preserved)
  • Control passes to the ON SIZE ERROR clause
  • The NOT ON SIZE ERROR clause (if present) is skipped

When SIZE ERROR does NOT trigger:

  • The NOT ON SIZE ERROR clause executes (if present)
  • The ON SIZE ERROR clause is skipped

SIZE ERROR also catches division by zero:

cobol
DIVIDE WS-DENOMINATOR INTO WS-NUMERATOR GIVING WS-RESULT
    ON SIZE ERROR
        MOVE ZERO TO WS-RESULT
        PERFORM LOG-DIVISION-ERROR
END-DIVIDE.

Always include ON SIZE ERROR for any arithmetic involving user-supplied or database-retrieved values. Internal counters with known bounds and constants are lower risk.

Financial Calculation Patterns

Simple Interest

cobol
COMPUTE WS-INTEREST ROUNDED =
    WS-PRINCIPAL * WS-ANNUAL-RATE * WS-DAYS / 365.

ADD WS-INTEREST TO WS-PRINCIPAL GIVING WS-MATURITY-VALUE.

Compound Interest

cobol
COMPUTE WS-FUTURE-VALUE ROUNDED =
    WS-PRINCIPAL * (1 + WS-PERIODIC-RATE) ** WS-PERIODS.

Pro-Rata Allocation

cobol
DIVIDE WS-TOTAL-ALLOCATION BY WS-PARTICIPANT-COUNT
    GIVING WS-PER-PARTICIPANT ROUNDED
    REMAINDER WS-UNALLOCATED.

Percentage Calculation

cobol
COMPUTE WS-PERCENTAGE ROUNDED =
    (WS-PART / WS-WHOLE) * 100.

*> Or using DIVIDE:
DIVIDE WS-WHOLE INTO WS-PART GIVING WS-RATIO.
MULTIPLY 100 BY WS-RATIO GIVING WS-PERCENTAGE ROUNDED.

Common Mistakes

Forgetting S on COMP-3 fields: PIC 9(9)V99 COMP-3 cannot store negative values. A subtraction that produces a negative result causes an S0C7 abend. Always declare financial fields as PIC S9(...)V99 COMP-3.

Mixing DISPLAY and COMP arithmetic: COBOL compilers convert between types automatically, but this incurs runtime overhead. Keep all intermediate calculations in COMP-3; convert to DISPLAY format only for output.

No SIZE ERROR on critical paths: Silent overflow truncates high-order digits. $1,234,567.89 overflowing into PIC 9(6)V99 stores $234,567.89 — a $1,000,000 error with no visible indication.

Integer division surprise: When both operands are integers, the result is an integer regardless of the receiving field's decimal places:

cobol
*> WS-A PIC 9(4) VALUE 10.
*> WS-B PIC 9(4) VALUE 3.
*> WS-RESULT PIC 9(4)V99.
DIVIDE WS-B INTO WS-A GIVING WS-RESULT.
*> Result: 3.00 — NOT 3.33 — because both operands are integer PIC 9

Use at least one COMP-3 or V-qualified operand to force decimal division.

Next Steps

Arithmetic is one part of COBOL's control flow. The next topic is structured control flow — IF/ELSE, EVALUATE (COBOL's switch statement), and the PERFORM statement in all its forms. See COBOL Control Flow, or return to the COBOL Mastery course.