Splitting digits from a packed-decimal field

1.5k Views Asked by At

I have a 7-digit packed-decimal field on my file. How can I define data items that would extract/separate these 7 digits?

For example I want to have the first two digits in one data item and the other digits in another, so I can manipulate them later.

2

There are 2 best solutions below

0
On

01 the-array.

03  filler pic x(02) value '00'.

03  filler pic x(02) value '01'.

03  filler pic x(02) value '02'.

and so on, until

03  filler pic x(02) value 'FF'.

01 two-array redefines the-array.

03  harry occurs 256 pic x(02).

91 sub1.

03  filler pic x(01) value low-values.

93  sub1-byte2 pic x(01).

01 sub2 redefines sub1 comp.

01 pd pic x(04).

01 pub pic 9(04).

01 eggs.

03  eggs1 pic x(01).

03  eggs2 pic x(01).

perform varying pub

from 1 by 1

until pub > 4

move pd(pub:1) to sub1-byte2

move harry(sub2 + 1) to eggs

display eggs1 egg2

end-perform.

So an array of 256 2 byte fields with values of '00' thru 'FF'.

step thru the 4 byte field that holds your packed decimal field.

use each byte as a subscript into the array (add 1 to ensure '00' points to first field in array).

2 byte field pointed to has the values of the 2 nibbles that represent that byte from the packed decimal field.

the right hand nibble of the fourth byte in the packed decimal field is for the sign.

0
On

In some other languages one of the things which may be common would be to "divide by a multiple of 10", an appropriate multiple, of course.

However, don't ever consider that with COBOL. A "divide" is "expensive".

       05  input-packed-decimal 
                            PACKED-DECIMAL PIC 9(7).

Then:

       05  FILLER 
           REDEFINES input-packed-decimal.
           10  ipd-split-two-and-five
                            PACKED-DECIMAL PIC 99V9(5).

   01  two-digits                          PIC 99.
   01  five-digits                         PIC 9(5).
   01  FILLER
       REDEFINES five-digits.
       05  five-digits-as-decimals         PIC V9(5).

       MOVE ipd-split-two-and-five  TO two-digits
                                       five-digits-as-decimals

Then you are able to use two-digits and five-digits for whatever you want.

Another way:

   01  ws-input-seven                      PIC 9(7).
   01  FILLER 
       REDEFINES ws-input-seven.
       05  two-digits                      PIC 99.
       05  five-digits                     PIC 9(5).

       MOVE input-packed-decimal    TO ws-input-seven

The first way will also work for signed source fields (just put an S in the appropriate place in each PICture clause).

The second will not work with signed fields, because the source sign will no propagate to the two-digits field because the MOVE is not even aware that there is such a field.

Take care when REDEFINESing PACKED-DECIMAL or BINARY fields (on an IBM Mainframe, these can also have USAGE COMP-3 and COMP/COMP-4/COMP-5). Always, when defining with the same, or similar, USAGE, define the same number of digits. For a REDEFINES field the compiler will always assume that you know what you are doing, so it will not do any "truncation of source" for you. So you have to ensure that you are not, explicitly or implicitly, expecting truncation of source when you use fields subordinate to a REDEFINES.

To get the second digit, don't ever do this:

       05  FILLER 
           REDEFINES input-packed-decimal.
           10  ignore-one-use-2nd-next-five
                            PACKED-DECIMAL PIC 9V9(5).

To get the second digit, use PACKED-DECIMAL PIC 99V9(5) as before, but define the receiving field with only one digit position. The compiler will happily then generate code to do the truncation you expect.

If you are "unable to use REDEFINES" you'll have to create a new field in the WORKING-STORAGE with the same characteristics as your input field, and use that.

The data-names I've used here are solely for this general explanation. Use good, descriptive, names to your task. If the first two digits are part-type, and the last five are part-number, make sure that is clear fro your naming.

Don't name them "Var(n)" or similar and don't give them names which are misleading.