Trey
Trey

Reputation: 31

How to REDEFINE and perform arithmetic on a PIC X clause in COBOL

I need to move a PIC X defined field that has numerics with a 2 position decimal to a numeric field to perform an arithmatic function involving a comp-3 field. What is the best way to do this?

I did do a redefine from the PIC X to a PIC 9 with the following: EX. PIC X(10) to PIC 9(7).99.

But now how do I perform a computation with that redefined field? Do I redefine the redefined field?

Compute FIELD-RESULT defined as S9(9)v99 = FIELD-1 (defined as S9(9)V99) - FIELD-2(my redefined field PIC 9(7).99.

Thanks!!

Upvotes: 3

Views: 21201

Answers (2)

Bill Woodger
Bill Woodger

Reputation: 13076

You can look at the intrinsic FUNCTION NUMVAL.

You need to have "good" data, as NUMVAL, on the Mainframe anyway, fails if given invalid data (text which is not a valid "edited" number).

COMPUTE X-TO-NUMERIC = FUNCTION NUMVAL ( text-data )

You can define like this:

01  TEXT-NUMBER PIC X(10).
01  EDITED-NUMBER REDEFINES TEXT-NUMBER PIC 9(7).99  (or Z(6)9.99 or Z(7)9.99 or whatever)
01  X-TO-NUMERIC PIC 9(7)V99.

MOVE EDITED-NUMBER TO X-TO-NUMERIC

Can still fail, or just be wrong, with invalid data.

Or, my preferred method:

01  CONVERTED-NUMBER PIC 9(7)V99.
01  FILLER REDEFINES CONVERTED-NUMBER.
    05  CN-INTEGER-PART PIC X(7).
    05  CN-DECIMAL-PART PIC XX.


01  TEXT-NUMBER PIC X(10).
01  FILLER REDEFINES TEXT-NUMBER.
    05  TN-INTEGER-PART  PIC X(7).
    05  TN-DECIMAL-POINT PIC X.
        88  TN-DECIMAL-POINT VALID VALUE ".".
    05  TN-DECIMAL-PART  PIC XX.

IF ( TN-INTEGER-PART NUMERIC )
AND ( TN-DECIMAL-PART NUMERIC )
AND ( TN-DECIMAL-POINT )
    MOVE TN-INTEGER-PART TO CN-INTEGER-PART
    MOVE TN-DECIMAL-PART TO CN-DECIMAL-PART
ELSE
    deal with invalid
END-IF

Won't fail, won't get incorrect results.

EDIT: Why haven't I suggested reference-modification? Much less easy to "read" for a human if using literals only, if using datanames, still not as clear and slower than the data-definition method, so I have changed them.

EDIT. Drawn here again by another question, I noticed: in this example. no need for CN-INTEGER-PART, CN-DECIMAL-PART, TN-INTEGER-PART or TN-DECIMAL-PART to be defined as numeric fields.

Upvotes: 4

NealB
NealB

Reputation: 16928

In the world of COBOL, what you are trying to do is "deedit" a numeric data type.

Given a PIC X(10) field holding a "number" convert it to a numeric data type. If this "number" is always guaranteed to have the same format: 7 digits, a decimal point and 2 more digits after the decimal, the classic way of doing this in COBOL is:

01.
   02 NUM-AS-PIC         PIC X(10).
   03 NUM-EDITED  REDEFINES NUM-AS-PIC PIC 9(7).99.

01 NUM-DEEDITED            PIC 9(7)V99.

MOVE '1234567.89' TO NUM-AS-PIC      <- alpha-numeric move
MOVE NUM-EDITED   TO NUM-DEEDITED    <- deediting numeric move

ADD 1 TO NUM-DEEDITED                <- numeric computation

MOVE NUM-DEEDITED  TO NUM-EDITED     <- recover explicit decimal (editing)
DISPLAY NUM-AS-PIC                   <- alpha-numeric display

The major drawback is that it is not very flexible. You will always need to ensure that NUM-AS-PIC contains exactly the correct format. For example

MOVE '123.45'  TO NUM-AS-PIC

would result in a runtime error because the decimal place is in the wrong position (MOVE fills from the left as opposed to the right) and trailing spaces are padded after it making up the remaining 4 bytes (and spaces are not valid numeric values).

Another common method is to employ the NUMVAL function. This function takes any valid edited number format and converts it to a floating point numeric representation. The numeric value may have leading or trailing spaces appended to it. The result of NUMVAL may be assigned to any valid numeric data type. For example:

  MOVE '1234567.89' TO NUM-AS-PIC         <- alpha-numeric move
  COMPUTE NUM-DEEDITED = FUNCTION NUMVAL(NUM-AS-PIC)

Now

  MOVE '123.45' TO NUM-AS-PIC 
  COMPUTE NUM-DEEDITED = FUNCTION NUMVAL(NUM-AS-PIC)

results in a valid move too. However, a runtime error still occurs if the value contained in NUM-AS-PIC cannot be converted to a valid floating point number. For example:

  MOVE '12A.23' TO NUM-AS-PIC
  COMPUTE NUM-DEEDITED = FUNCTION NUMVAL(NUM-AS-PIC)

will still result in a runtime error.

The sad news is that there is no universally easy or fool-proof way of doing this in COBOL.

Upvotes: 1

Related Questions