Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to set up COMPUTE with variable field formats

Status
Not open for further replies.

rasETL

IS-IT--Management
May 28, 2003
213
US
I have two numeric fields on an input record.

I do not know the format, however there is another set of fields on the input record which I can use to determine the formats.

There is also a field that allows me to determine the desired format of the results of the COMPUTE.

Basically each of the fields could be one of 5 formats - a whole number or 1,2,3, or 4 decimal places.

Moving each of the 2 input fields to a field with the appropriate PIC clause isn't too bad - 5 Evaluate...When statements for each.

However, how do I efficiently handle the COMPUTE? I would hate to set up 125 Evaluate...When statements since the combinations are 5 x 5 x 5.

Any ideas???
 
Define the COMPUTE result in WORKING-STORAGE for the maximum size. Then use reference modification to move the result to the output area. This assumes the output data USAGE is DISPLAY.

If the output data USAGE is not DISPLAY, it gets more complicated, but not unduly so.
 
Hi R,

Using the same assumptions as WR, I'd ignore the dec places and multiply the 2 fields.

Set up the receiving field as:
Code:
01  ws-no-dec      pic 9(10).    
01  ws-1-dec       redefines    
01  ws-no-dec      pic 9(09)v9(01).   
01  ws-2-dec       redefines    
01  ws-no-dec      pic 9(08)v9(02).             
    .
    .
   etc.

Then multiply:
Code:
compute ws-no-dec = ws-fld-1 * ws-fld-2
Then eval the sum of the field lengths to decide which
ws-n-dec to use. Unless I missed something, it should work.

Regards, Jack.
 
A compilable definition would be:

01 ws-no-dec pic 9(10).
01 ws-1-dec redefines
ws-no-dec pic 9(09)v9(01).
01 ws-2-dec redefines
ws-no-dec pic 9(08)v9(02).




 
Why not define two working fields with the max number of decimal places? Also, define the result field with the max number of decimals.

01 WS-FLD-1 PIC S9(09)V9999.
01 WS-FLD-2 PIC S9(09)V9999.
01 WS-ANSWER PIC S9(09)V9999.

Use your EVALUATE to move the proper definition of the input into each of the 2 working fields. It will pad zeroes in the unused decimal portions. You can then do one COMPUTE statement with the result in WS-ANSWER. Now you can move that to an appropriately defined output field and it will truncate the unneeded decimal positions.

 
I appreciate everyone's help.

Lunker's solution is the solution I came up with late last night. It seems to be the cleanest way to approach this, and from a coding standpoint will be easy to follow.

I simplified things a little in order to ask the question. In reality the process I am developing is a calculation process that will be totally data-driven. The 2 input fields can be different formats and sizes, and the output result can be a number of different sizes and formats. The COMPUTE process can also be +,-,*,/. FUN...FUN...FUN



 
rsaanders,

You did not specify what the output is to be, but be aware that you are in danger of losing precision, especially important when you are going to have multiple arithmetic operations strung together.

Check your compiler vendor to see if the number of digits supported isn't greater than 18. Then, use all the digits available to you in your accumulator, with sufficient digits to the right of the decimal place (perhaps
Code:
 pic 9(15)v9(15)
).

It is only slightly more complex (given that you are building an engine to be driven by data input) to separate the integer and fractional parts of the inputs and accumulator to provide even more precision. For example:
Code:
01  input-integer  pic 9(18).
01  input-fraction pic v9(18).
...
move some-numeric-item to input-integer, input-fraction.
Extended precision arithmetic is something everybody should do at least once. [glasses]

Tom Morrison
 
You're right Crox! I was cut & pasting and forgot to remove the "01"s.

Rsaanders,

I'm not sure I see how you align the dec pt in Lunker's solution. Do you plan to ref/mod move the data in? Or multiply redefine WS-FLD-1, etc.?

You mention "different sizes and formats". Is the "formats" used here dec pt formats or data formats, as in binary, packed decimal, display, etc.?

As Tom says, precision can bite you, especially when using COMPUTE. That's why I suggested doing the math with integers then calculating (adding) the decimal places.

Regards, Jack.
 
Hi,

If you are working with a modern COBOL compiler (for example IBM's COBOL 390 version 2.2), you can even use 31 digits. If this is your situation, you can use even something like

01 GENERAL-FIELD-01 PIC S9(18)V9(13).

You won't lose digits so fast and you don't have to use a lot of calculations. The compiler can do it for you.

Best regards,

Crox
 
If Rsaanders can use a compiler that supports the increased capacity (31) of the numeric PIC clause, I like this solution.

What I like about it is that it only uses 3 COMPUTEs and an IF.

The numeric formats could be tweaked for performance, but I didn't want to cloud the issue.

Code:
 01  IP-REC.
     05  IP-FLD-1-INTEGER     PIC  9(007).
     05  IP-FLD-1-DEC-PLACES  PIC  9(001).
     05  IP-FLD-2-INTEGER     PIC  9(007).
     05  IP-FLD-2-DEC-PLACES  PIC  9(001).



     05  WS-PROD-FLD-1        PIC  9(014)V9(008).
     05  WS-PROD-DEC-PLACES   PIC  9(001).

     05  WS-DEVIDE-TBL        VALUE
         '00000001000000100000010000001000'
         '00010000001000000100000010000000'.
         10  WS-DEVIDE-ENT    PIC  9(008)
             OCCURS 8.


*  Multiply the 2 flds using NO decimal 
*  places

   COMPUTE WS-PROD-FLD-1 = IP-FLD-1-INTEGER
                         * IP-FLD-2-INTEGER

*  Find the # of dec places in the product 
*  above

   COMPUTE WS-PROD-DEC-PLACES 
         = IP-FLD-1-DEC-PLACES
         + IP-FLD-2-DEC-PLACES

*  If the product has dec places, divide the 
*  integer by the appropriate table value. 
*  If one dec place devide by 10, if 2 
*  devide by 100, if 3 ... etc.

   IF WS-PROD-DEC-PLACES    > ZERO
      COMPUTE 
         WS-PROD-FLD-1 
       = WS-PROD-FLD-1
       / WS-DEVIDE-ENT(WS-PROD-DEC-PLACES)
   END-IF
 
Here's the PIC 9(18) version. Using "on size error" might be prudent here if you're not sure of the field values:
Code:
 01  IP-REC.
     05  IP-FLD-1-INTEGER     PIC  9(007).
     05  IP-FLD-1-DEC-PLACES  PIC  9(001).
     05  IP-FLD-2-INTEGER     PIC  9(007).
     05  IP-FLD-2-DEC-PLACES  PIC  9(001).



     05  WS-PROD-FLD-W        PIC  9(018).
     05  WS-PROD-FLD-1        PIC  9(010)V9(008).

     05  WS-PROD-DEC-PLACES   PIC  9(001).

     05  WS-DEVIDE-TBL        VALUE
         '00000001000000100000010000001000'
         '00010000001000000100000010000000'.
         10  WS-DEVIDE-ENT    PIC  9(008)
             OCCURS 8.


*  Multiply the 2 flds using NO decimal 
*  places

   COMPUTE WS-PROD-FLD-W = IP-FLD-1-INTEGER
                         * IP-FLD-2-INTEGER

*  Find the # of dec places in the product 
*  above

   COMPUTE WS-PROD-DEC-PLACES 
         = IP-FLD-1-DEC-PLACES
         + IP-FLD-2-DEC-PLACES

*  If the product has dec places, divide the 
*  integer by the appropriate table value. 
*  If one dec place devide by 10, if 2 
*  devide by 100, if 3 ... etc.

   IF WS-PROD-DEC-PLACES    > ZERO
      COMPUTE 
         WS-PROD-FLD-1 
       = WS-PROD-FLD-W
       / WS-DEVIDE-ENT(WS-PROD-DEC-PLACES)
   ELSE
      MOVE WS-PROD-FLD-W   TO WS-PROD-FLD-1 
   END-IF

 
I had the table wrong. Here's what it should be. BTW, does anybody know how to edit a post afeter it's sent? Is it possible here?

Thanx, Jack.

Code:
    ********************************************
    *  This table is used to determine where to
    *  position the decimal place in the product
    *  of the two integers.
    ********************************************
     05  WS-DEVIDE-TBL        VALUE
         '000000010000000100000001000000010000'
         '000100000001000000010000000100000000'.
         10  WS-DEVIDE-ENT    PIC  9(009)
             OCCURS 8.
 
jack,

Some of us never have to edit a post. [lol]

Tom Morrison
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top