ON SIZE ERROR
What happens when a result is too big for its field? Run this:
IDENTIFICATION DIVISION.
PROGRAM-ID. OVERFLOW.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-X PIC 99 VALUE 95.
01 WS-Y PIC 99 VALUE 95.
PROCEDURE DIVISION.
ADD 10 TO WS-X
DISPLAY "WITHOUT CHECK: " WS-X
ADD 10 TO WS-Y
ON SIZE ERROR
DISPLAY "SIZE ERROR, WS-Y STILL " WS-Y
NOT ON SIZE ERROR
DISPLAY "OK"
END-ADD
STOP RUN.
Output:
WITHOUT CHECK: 05
SIZE ERROR, WS-Y STILL 95
95 + 10 = 105, which needs three digits. Without a check, the leading 1
is silently lost and WS-X becomes 05 — a customer's balance of 105,000
turning into 5,000 is exactly this bug. With ON SIZE ERROR, the receiving
field is left unchanged and your error code runs instead.
What counts as a size error
- The integer part of the result doesn't fit the receiving field.
(Extra decimal places are not a size error — they're truncated, or
rounded if you said
ROUNDED.) - Division by zero.
- Rounding pushes the value over the top:
9.996intoPIC 9V99withROUNDEDwould need10.00, so that's a size error too.
The full shape
Every arithmetic verb takes the same optional phrases:
DIVIDE WS-TOTAL BY WS-COUNT GIVING WS-AVERAGE ROUNDED
ON SIZE ERROR
MOVE ZERO TO WS-AVERAGE
DISPLAY "CANNOT AVERAGE"
NOT ON SIZE ERROR
DISPLAY "AVERAGE CALCULATED"
END-DIVIDE
NOT ON SIZE ERROR runs only when the arithmetic succeeded. Both branches
can hold several statements. The scope terminator END-DIVIDE (or
END-ADD, END-SUBTRACT, END-MULTIPLY, END-COMPUTE) marks where the
error branch ends. Leave it out and the next statements — up to the next
period — are swallowed into the NOT ON SIZE ERROR branch. The conditions
module shows how nasty that gets; for now, always write the terminator.
Division by zero without a check
In GnuCOBOL, DIVIDE by zero with no ON SIZE ERROR leaves the target
unchanged and carries on. On z/OS the same code can abend the job
(typically a S0CB decimal-divide exception) at 3 a.m. Either test the
divisor first or use ON SIZE ERROR — never rely on what happens by
default.
On the job
Shop standards often require ON SIZE ERROR on every COMPUTE or
DIVIDE that feeds a money field, with the error branch writing a
message and setting a return code so operations can see the run needs
attention.
Your task
A savings account balance is held in WS-BALANCE PIC 9(5)V99, so it can't
exceed 99,999.99. The program reads the current balance, a
deposit and a number of months, one per line.
- Add the deposit to
WS-BALANCE. If it doesn't fit, displayDEPOSIT REJECTEDand leave the balance as it was; otherwise displayDEPOSIT ACCEPTED. - Display
BALANCE:followed by the balance throughWS-OUT. - Divide the balance by the number of months, rounded to the cent, into
WS-MONTHLY. If that fails (0 months), displayMONTHLY: N/A; otherwise displayMONTHLY:and the amount throughWS-OUT.
For 90000.00, 5000.50, 12:
DEPOSIT ACCEPTED
BALANCE: 95,000.50
MONTHLY: 7,916.71