Reputation: 31
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
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
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