How to convert a alphanumeric string into numeric decimal in COBOL
Solution 1
Asusually, I could find out a way to achieve it!
As said above, UNSTRINGing and combining didnt work, but REDEFINES works!
Get alphanumeric string redefined into two numeric fields to hold and process decimal part and integer part individually. Atlast divide the decimal-total by 1000 and add it to integer-part. Thats it! Code snippets follow...
01 WS-NUM-STR PIC X(14) VALUE 'ABCDEF 0 0.450'.
01 WS-NUM-STR-MOD REDEFINES WS-NUM-STR.
05 FILLER PIC X(9).
05 WS-INT-PART PIC 9.
05 FILLER PIC X.
05 WS-DEC-PART PIC 999.
----------
----------
* CODE TO ADD ALL INTEGER PARTS
* CODE TO ADD ALL DECIMAL PARTS
COMPUTE = INTEGER-TOTAL + (DECIMAL-TOTAL / 1000)
Note: As I already knew that decimal part has 3 digits, I divided DECIMAL-TOTAL by 1000. Hope you could figure out.
And Please suggest any other way to achieve the same!
Solution 2
I assume the format is not fixed, since then you could just pick that part of the string and move it to a field defined with pic 9.999 and use it from there.
This assumes the string value is made up of 3 parts separated by spaces. First define some fields:
1 part1 pic x(14).
1 part2 pic x(14).
1 part3 pic x(07).
1 digitsAn.
2 digits pic 9(03).
1 decimalsAn.
2 decimals pic .9(03).
1 theValue pic 9(03)v9(3).
The An suffix is from my naming convention, and indicates a alphanumeric value. If the string input may be longer increase the sizes as needed.
The rest of the code parses theString into theValue.
* Extract the third part.
initialize part3
unstring theString delimited by all spaces into part1 part2 part3
* make sure the receiving field contains numeric data.
inspect part3 replacing spaces by zeroes
* extract digits before and after the decimal point.
unstring part3 delimited by "." into digits decimalsAn(2:)
* Combine parts before and after decimal points into a numeric value.
compute theValue = digits + decimals
Beware, I haven't run this through a compiler!
Solution 3
For eg., i have alphanumeric string 'ABCDEF 0 0.450' and i need to get '0.450' as numeric decimal and do arithmetic on it. Do we have a way? Please suggest.
If you are running in CICS, you could use the BIF DEEDIT function -- that will leave you with "00.450".
If you are not running in CICS, assume you have your string in a field called WS-STR:
Move 0 to JJ
Perform varying II from 1 by 1
until II > Length of WS-STR
Evaluate WS-STR (II:1)
when '0'
when '1'
when '2'
when '3'
when '4'
when '5'
when '6'
when '7'
when '8'
when '9'
when '.'
Add 1 to JJ
Move WS-STR (II:1) to WS-NUM (JJ:1)
* ---- Do nothing
when other
continue
End-Perform
Compute REAL-DEC-NUM = Function NUM-VAL (WS-NUM)
Solution 4
In most modern Cobol compilers, you can move a numeric-edited field to a numeric field.
Borrowing from your example below:
01 WS-NUM-STR PIC X(14) VALUE 'ABCDEF 0 0.450'.
01 WS-NUM-STR-MOD REDEFINES WS-NUM-STR.
05 FILLER PIC X(9).
05 WS-EDITED-NUMBER PIC 9.999.
01 WS-NUMBER PIC 9V999.
----------
MOVE WS-EDITED-NUMBER TO WS-NUMBER
And then, do the calculation with WS-NUMBER.
Raja Reddy
I'm a Mainframe developer worked for Telecom company and now work for a Banking client. Passionate towards upcoming stuff in mainframe era!!
Updated on June 24, 2020Comments
-
Raja Reddy almost 4 years
For eg., i have alphanumeric string 'ABCDEF 0 0.450' and i need to get '0.450' as numeric decimal and do arithmetic on it. Do we have a way? Please suggest.
-
Raja Reddy about 14 yearsKwebble, UNSTRINGing into some NON-STRING variables didn't work. I believe, the receiving fields should be 'STRING's too. What do you say?
-
Kwebble about 14 yearsA typo, the first receiving field should be digitsAn instead of digits:unstring part3 delimited by "." into digitsAn decimalsAn(2:)
-
Kwebble about 14 yearsYes, for a fixed format define a structure accordingly. I doubt you need to redefine the field. What about WS-NUM-STR consisting of a dummy field of pic x(9) and the value field of pic 9.999?
-
Raja Reddy about 14 yearsAs I was keen about the Numeric field, didnt bother about the filler, but updated above. Coming to redefining with value field of PIC 9.999 doesnt work because 9.999 is a picture edited type, which will be useful for displaying/output purpose and will still not be able to do the required arithmetic. Lemme know what do you think.
-
Raja Reddy almost 14 yearsI tried the same, but didnt work. Morevoer i got SOC7 abend. SO had to go to other way.. Anyhow thanks for your interest and response Gilbert
-
Raja Reddy almost 14 yearsThis is something like moving numeric fields manually around the decimal '.' right! Thanks for your time...
-
Joe Zitzelberger almost 14 yearsThe problem with moving it to a numeric field is that ABCDEF are actually valid zoned-decimal digits. If the spaces were not there, the ABCDEF would not give you a problem, but would not give you the results you expect as the would be erroneously interpreted as digits. The spaces really do you a favor by causing the SOC7 (Numeric Exception) on the intermediate arithmetic fields.
-
Bill Woodger over 11 yearsRaja, If done correctly, as Gilbert's is, I don't see how you'll S0C7. Any other readers, this is a solution which will work with data at fixed positions.
-
Bill Woodger over 11 yearsJoe, it is WS-EDITED-NUMBER from the REDEFINES which is being MOVEd, so no spaces. Spaces also are pretty good at "disguising" themselves as "zoned"/"display" numerics (zeros), it is on when they get in the "sign" left-most "half" of the right-most byte that they "might" (depending on other things) cause a S0C7.
-
Bill Woodger over 10 yearsYou can't define your field decimals like that and use it in a COMPUTE. It should be V999. Compilers I know, anyway.
-
Bill Woodger over 10 yearsYou do not need to divide by 1000. Just define WS-DEC-PART as PIC V999 and ADD. If doing it that way, you should check that the decimal point is a decimal point, and you should check that your numeric fields are numeric.