Search code examples
cobolgnucobol

GnuCOBOL PIC 999V99 - unexpected result?


What am I doing wrong with the following piece of code under GnuCOBOL 3.1-rc1.0?

   IDENTIFICATION DIVISION.
   PROGRAM-ID.     NUMTEST.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
    01 NUM         PIC 999V99.
   PROCEDURE DIVISION.
       DISPLAY "ENTER NUMBER: ". 
       ACCEPT NUM.
       DISPLAY "NUMBER = ".
       DISPLAY NUM.
       STOP RUN.

I enter 123.45 as my input. I'm expecting 123.45 as the output, but instead I get 123.40


Solution

  • These are plain ACCEPTs, they only read in data from the command line (you can also enter a big lorem ipsum there).

    While I think it is a reasonable request to have this working "as expected" the best option you currently have is ACCEPTing only PIC X and then use MOVE FUNCTON NUMVAL (INPUT-DATA) TO NUM (maybe test the data with FUNCTION TEST-NUMVAL() before). For DISPLAY you likely want an edited field with a PICTURE like ZZ9.99.

    In any case: be aware that V is an implied decimal point, it is not part of the actual storage.

    Using "extended" screenio (= input not from the command line) gives some benefits (like only allowing numeric data and not more than the fields's size) but has different culprits (for example you should use COLUMN/LINE for it and numeric ACCEPT still has some issues in GC 3.1).

    As suggested by JoelFan I've tested edited fields - these work currently only correctly when in "command line mode" (so not if any attributes like positioning is used):

           PROGRAM-ID.     NUMTEST.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
            01 NUM-INP     PIC 999.99.
            01 NUM         PIC 999V99.
            01 NUM-OUT     PIC zz9.99.
           PROCEDURE DIVISION.
               DISPLAY "ENTER NUMBER: ". 
               ACCEPT NUM-INP.
               DISPLAY "NUMBER = ".
               MOVE NUM-INP TO NUM
               MOVE NUM     TO NUM-OUT
               DISPLAY NUM "/" NUM-OUT.
               STOP RUN.
    

    Producing the expected result:

    ENTER NUMBER:
    123.45
    NUMBER =
    123.45/123.45
    
    ENTER NUMBER:
    1.2
    NUMBER =
    001.20/  1.20
    
    ENTER NUMBER:
    a
    NUMBER =
    000.00/  0.00
    
    ENTER NUMBER:
    1234567
    NUMBER =
    567.00/567.00
    

    Note: the third case should actually raise an exception when compiled with -fec=all / -debug (currently doesn't), the last case is completely correct as numbers are right justified.

    Still: ACCEPTing alphanumeric data, do explicit checks/conversions, and display as edited field like NUM-OUT above is the safest option.