Cobol COMP-3 value changes after write to dataset

1.9k Views Asked by At

SOLVED

I found this line buried much past where I am moving these values to the output file:

INSPECT OUT-RECORD REPLACING ALL X'00' BY ' '

changing my X'00' to X'40', which is where I'm getting the mysterious '4'. I will attribute this to my first Cobol version of the missing ";".

Thank you to Bruce and anonymous user user9835153 for your help!


I need some help with a strange scenario I've never encountered before.

I have an unsigned zoned decimal numeric as input, PIC 9(3).9(6), and I need to write it out to a dataset as a signed COMP-3, PIC S9(3)V9(6). This works fine for all values except when zeros surround the decimal in the input. The 0 before the decimal is always changed to 4 in this case.

Example: when the input value is 31.006261, it gets written as +31.006261 (x'031006261C' in the actual output file). But, when the input value is 30.006261, it is written out to the file as +34.006261 (x'034006261C').

I cannot change the how the value comes in, but I can change the input layout. I have tried a variety of ways of moving this value, including: moving straight to COMP-3 from input, moving to different types of temp fields in working storage, making the input a character field and moving to numeric (ignoring the decimal completely).

Here's a simplified version of what I'm doing:

* Value 30.006261 is read into WS-IN-VAL from input file. 

01 WS-IN-RECORD.
   05 WS-IN-VAL      PIC 9(3).9(6).

01 OUT-RECORD.
   05 WS-OUT-VAL     PIC S9(3)V9(6) COMP-3.

* Working Storage 01 area
   05 WS-HOLD-VAL       PIC 9(3)V9(6).
   05 WS-DISP-VAL       PIC +9(3).9(6).

MOVE WS-IN-VAL   TO WS-HOLD-VAL.
MOVE WS-HOLD-VAL TO WS-OUT-VAL.
MOVE WS-OUT-VAL  TO WS-DISP-VAL.

WRITE WS-OUT-RECORD.

DISPLAY 'VALUE IN:   ' WS-IN-VAL.                
DISPLAY 'HOLD VALUE: ' WS-HOLD-VAL.
DISPLAY 'VALUE OUT:  ' WS-OUT-VAL.
DISPLAY 'FORMATTED:  ' WS-DISP-VAL.

VALUE IN:   30.006261                
HOLD VALUE: 030006261
VALUE OUT:  030006261
FORMATTED:  +030.006261

However, when I open the output file with HEX ON here's what I get:

----+
04021
3066C  

View of the file with a layout shows: +34.006261.

This happens EVERY time zeros surround the decimal. I used a subset of data, of 8 records, and changed half to 10.1xxxxx and the other half to 10.0xxxxx (x's are various numbers). All 10.0xxxxx records changed to 14.0xxxxx but the 10.1xxxxx records stayed as correct. Did this with 20.x, 30.x, 40.x, etc. and got the same results.

I have also tried COMPUTE instead of MOVE when going from unsigned to signed -- same results. Like I mentioned before, I tried various methods of moving the input values but the results are always the same. I thought maybe part of the explicit decimal (x'4B') was somehow getting placed in the upper nibble, so I modified the input to read it separately, and changed it's hex values to x'00', but that didn't work either. I'm completely lost as to what else to try and can't find anyone else that's experienced this.

Any ideas or suggestions as to why the 0 before the decimal is getting replaced by 4?

Edit 5/21/18 after a suggestion was provided:

VALUE FROM FILE:              50.022287  
VALUE AFTER MOVE:             050022287
VALUE AS COMP-3 (OUTPUT FLD): 050022287
OUTPUT DISPLAYED:             +050.022287

VALUE IN FILE: +54.022287

The zero before the decimal still changes after writing to dataset.

2

There are 2 best solutions below

1
On BEST ANSWER

Here is a complete COBOL program compiled and run under IBM Enterprise COBOL for z/OS 4.2.0. It does not display the behaviour that you have described:


   IDENTIFICATION DIVISION.
   PROGRAM-ID. COMP3.
   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.
        SELECT OFILE  ASSIGN TO OFILE STATUS OFILE-STAT.
   DATA DIVISION.
   FILE SECTION.
    FD  OFILE
        LABEL RECORDS STANDARD
        RECORDING MODE F
        BLOCK CONTAINS 0 RECORDS.

    01  OFILE-REC.
        02 COMP3-NBR                PIC S9(3)V9(6) COMP-3.
        02                          PIC X(75).

   WORKING-STORAGE SECTION.
   01  WS-IN-VAL                    PIC 9(3).9(6).
   01  WS-OUT-VAL                   PIC S9(3)V9(6) COMP-3.
   01  WS-OUT-VAL-X REDEFINES WS-OUT-VAL
                                    PIC X(5).
   01  WS-HOLD-VAL                  PIC 9(3).9(6).
   01  WS-DISP-VAL                  PIC +9(3).9(6).
   01  OFILE-STAT                   PIC 9(2).
       88 OFILE-STAT-OK             VALUE ZERO.
   PROCEDURE DIVISION.
       MOVE 30.006216       TO WS-IN-VAL
       MOVE WS-IN-VAL       TO WS-HOLD-VAL
       MOVE WS-HOLD-VAL     TO WS-OUT-VAL
        02                          PIC X(75).

   WORKING-STORAGE SECTION.
   01  WS-IN-VAL                    PIC 9(3).9(6).
   01  WS-OUT-VAL                   PIC S9(3)V9(6) COMP-3.
   01  WS-OUT-VAL-X REDEFINES WS-OUT-VAL
                                    PIC X(5).
   01  WS-HOLD-VAL                  PIC 9(3).9(6).
   01  WS-DISP-VAL                  PIC +9(3).9(6).
   01  OFILE-STAT                   PIC 9(2).
       88 OFILE-STAT-OK             VALUE ZERO.
   PROCEDURE DIVISION.
       MOVE 30.006216       TO WS-IN-VAL
       MOVE WS-IN-VAL       TO WS-HOLD-VAL
       MOVE WS-HOLD-VAL     TO WS-OUT-VAL
       MOVE WS-OUT-VAL      TO WS-DISP-VAL
       DISPLAY 'VALUE IN: ' WS-IN-VAL
       DISPLAY 'HOLD VAL: ' WS-HOLD-VAL
       DISPLAY 'OUT VAL : ' WS-OUT-VAL
       DISPLAY 'OUT VALX: ' WS-OUT-VAL-X
       OPEN OUTPUT OFILE
       IF NOT OFILE-STAT-OK THEN
          DISPLAY "OFILE OPEN STATUS: " OFILE-STAT
          STOP RUN
       END-IF
       INITIALIZE OFILE-REC
       MOVE WS-OUT-VAL  TO COMP3-NBR
       WRITE OFILE-REC
       IF NOT OFILE-STAT-OK THEN
          DISPLAY "OFILE WRITE STATUS: " OFILE-STAT
          STOP RUN
       END-IF
       GOBACK
       .


SYSOUT:


******************************** Top of Data ***********************************
VALUE IN: 030.006216
HOLD VAL: 030.006216
OUT VAL : 030006216
OUT VALX: : ::%
 ******************************* Bottom of Data ********************************

and OFILE content displayed in hex:


****** ***************************** Top of Data ******************************
000001     %
       000260000000000000000000000000000000000000000000000000000000000000000000
       3061C0000000000000000000000000000000000000000000000000000000000000000000
------------------------------------------------------------------------------
****** **************************** Bottom of Data ****************************

It all looks good to me! I think you must have some other problem buried in your code somewhere.

1
On

In earlier versions of Cobol 9(3).9(6) would be a Edited-numeric -> character field. I am not sure what the current standard / ibm implementations are supposed to do, You could check with IBM / IBM manuals to what is supposed to happened.

I would probably code it as

01 WS-IN-RECORD.
   05 WS-IN-VAL      PIC 9(3).9(6).
   05 redefines WS-IN-VAL.
      10 WS-IN-VAL-pt1        pic 9(3)
      10                      pic x.
      10 WS-IN-VAL-Decimal    pic v9(6)

and

    Add WS-IN-VAL-pt1         to WS-IN-VAL-Decimal
                          Giving ...

Possible Experiment

Try defining

01 WS-IN-RECORD.
   05 WS-IN-VAL-X.
      10 WS-IN-VAL      PIC 9(3).9(6).

and try moving WS-IN-VAL-X in as well as WS-IN-VAL and see if the result is the same