You are on page 1of 4

Did you remember to test for numerics?

When performing data validation on zoned decimal numeric fields in COBOL, always
check for NUMERIC. Never rely upon IFs and 88s alone! This article will demonstrate
why.

I love 88s (condition names.) I often tell my students that I find them to be one of the
nicest features in COBOL. But IF statements, with or without 88s, when performed on
zoned decimal numeric fields, disregard the sign bits of all but the last digit.
Consequently, it is possible to have a non-numeric character, such as any letter of the
alphabet, in a supposed numeric field, and that field be treated as a number. IFs and 88s
won’t catch the error. However, at least to my knowledge, COBOL’s check for
NUMERIC cannot be fooled. Consider the following example

DATA DIVISION.
WORKING-STORAGE SECTION.
01 MISC.
05 INPUT-FLD-AS-X PIC X(5).
05 INPUT-FLD-AS-9 REDEFINES INPUT-FLD-AS-X PIC 9(3)V99.
88 VALID-VALUES VALUE 100 THRU 199.99.
05 OUTPUT-FLD-AS-Z PIC ZZ9.99.

Given: MOVE '13E79' TO INPUT-FLD-AS-X


then: IF INPUT-FLD-AS-9 IS NUMERIC is false
but: IF VALID-VALUES is true
and: IF INPUT-FLD-AS-9 >= 100 AND INPUT-FLD-AS-9 <= 199.99 is true
and: MOVE INPUT-FLD-AS-9 TO OUTPUT-FLD-AS-9 gives 135.79

The reason for this is that C’13E79’ is equivalent to X’F1F3C5F7F9’ and when
COBOL’s IF looks at a zoned decimal field, it ignores the zone bits (X’F’ and X’C’) in
all but the rightmost byte. Indeed, the COBOL compiler will generate a machine level
PACK instruction for the purpose of the compare (since zoned decimal instructions do
not exist at the machine level) and this value packs to X’13579F’, which is a valid packed
decimal numeric field.

So you should never rely upon a range check alone (with or without an 88.) The data
could be properly checked as follows: IF INPUT-FLD-AS-9 IS NUMERIC AND
VALID-VALUES
Source Code:

000100 IDENTIFICATION DIVISION.


000200 PROGRAM-ID. NUMTEST.
000300
000400 ENVIRONMENT DIVISION.
000500
000600 DATA DIVISION.
000700 WORKING-STORAGE SECTION.
000800 01 MISC.
000900 05 INPUT-FLD-AS-X PIC X(5).
001000 05 INPUT-FLD-AS-9 REDEFINES INPUT-FLD-AS-X PIC 9(3)V99.
001100 88 VALID-VALUES VALUE 100 THRU 199.99.
001200 05 OUTPUT-FLD-AS-Z PIC ZZ9.99.
001300
001400 PROCEDURE DIVISION.
001500
001600 READY-GO.
001700 MOVE '09H7F' TO INPUT-FLD-AS-X.
001800 PERFORM SHOW-IT.
001900
002000 MOVE '12345' TO INPUT-FLD-AS-X.
002100 PERFORM SHOW-IT.
002200
002300 MOVE '13E79' TO INPUT-FLD-AS-X.
002400 PERFORM SHOW-IT.
002500
002600 MOVE '2C45F' TO INPUT-FLD-AS-X.
002700 PERFORM SHOW-IT.
002800
002900 STOP RUN.
003000
003100 SHOW-IT.
003200 DISPLAY 'INPUT IS ' INPUT-FLD-AS-X.
003300
003400 IF INPUT-FLD-AS-9 IS NUMERIC
003500 DISPLAY 'NUMERIC'
003600 ELSE
003700 DISPLAY 'NOT NUMERIC'
003800 END-IF
003900
004000 IF VALID-VALUES
004100 DISPLAY 'VALID VALUE'
004200 ELSE
004300 DISPLAY 'NOT VALID VALUE'
004400 END-IF
004500
004600 IF INPUT-FLD-AS-9 < 100
004700 DISPLAY 'LESS THAN 100'
004800 ELSE
004900 IF INPUT-FLD-AS-9 > 199.99
005000 DISPLAY 'GREATER THAN 199.99'
005100 ELSE
005200 DISPLAY 'BETWEEN 100 AND 199.99'
005300 END-IF
005400 END-IF
005500
005600 MOVE INPUT-FLD-AS-9 TO OUTPUT-FLD-AS-Z
005700
005800 DISPLAY OUTPUT-FLD-AS-Z.
005900
Results:

INPUT IS 09H7F
NOT NUMERIC
NOT VALID VALUE
LESS THAN 100
98.76

INPUT IS 12345
NUMERIC
VALID VALUE
BETWEEN 100 AND 199.99
123.45

INPUT IS 13E79
NOT NUMERIC
VALID VALUE
BETWEEN 100 AND 199.99
135.79

INPUT IS 2C45F
NOT NUMERIC
NOT VALID VALUE
GREATER THAN 199.99

You might also like