Menu

#1241 Loss of a decimal place when reading a PIC 9(2)V99 field with ACCEPT

GC 3.x
open
nobody
None
5 - default
20 hours ago
4 days ago
No

After thinking it over for a while, I’ve decided to report this bug after all. In my opinion, it’s a bug.

GnuCOBOL does not correctly read the field WS-UNIT-PRICE PIC 9(2)V99 using ACCEPT. When entering 12.99, only the value 12.90 is accepted. This results in an incorrect calculation. The user is also not warned.

All other compilers (Microsoft, RM, Micro Focus, gcobol-16) do indeed correctly read the input of 12.99 as the value 12.99. Only GnuCOBOL reads it as 12.90.

I would expect that when a PIC 9(2)V99 field is read directly into the console using ACCEPT, the correct value entered by the user would be accepted without first having to convert the input using TEST-NUMVAL and NUMVAL.

Many sample programs in textbooks use ACCEPT directly with PIC 9(2)V99 fields.

GnuCOBOL should work the same way as the other compilers mentioned above, especially since GnuCOBOL is in the same league in terms of platforms (Linux, Windows) and usage.

After all, the line MOVE “12.99” TO WS-UNIT-PRICE works (just) in GnuCOBOL without losing a decimal place. So the internal code for this could probably be used for a fix :-)

Example program and screenshot with tests (GnuCOBOL, Rocket Visual COBOL and GCC-COBOL-16) are attached.

2 Attachments

Discussion

  • Michael Del Solio

    Another thought why I think its a bug:

    According to the current GnuCOBOL Programmer’s Guide, section 7.8.1.1, when the receiving identifier of ACCEPT is numeric, the character value read from the console “will be parsed according to the rules for input to the NUMVAL intrinsic function”.

    Section 8.1.69 explicitly specifies #.# as a valid NUMVAL input format and states that the period represents the decimal separator.

    Therefore, for

    WS-UNIT-PRICE PIC 9(2)V99

    the statement

    ACCEPT WS-UNIT-PRICE

    with console input 12.99 should result in the numeric value 12.99. Instead, GnuCOBOL produces 12.90.

    This appears to contradict GnuCOBOL’s documented ACCEPT semantics, independently of the behaviour of other COBOL implementations.

     

    Last edit: Michael Del Solio 2 days ago
  • Mickey White

    Mickey White - 2 days ago

    My thoughts. The COBOL ISO_IEC 1989_2023-CD2_2.pdf says, althought I could be wrong:

    FORMAT 1
    1)The ACCEPT statement causes the transfer of data from the device. This data replaces the content of the data item referenced by identifier-1. Any conversion of data required between the device and the data item referenced by identifier-1 is defined by the implementor.
    2)The implementor shall define, for each device, the size of a data transfer.
    3)If a device is capable of transferring data of the same size as the receiving data item, the transferred data is stored in the receiving data item.
    4)If a device is not capable of transferring data of the same size as the receiving data item, then:
    a)If the size of the receiving data item (or of the portion of the receiving data item not yet currently occupied by transferred data) exceeds the size of the transferred data, the transferred data is stored aligned to the left in the receiving data item (or the portion of the receiving data item not yet occupied), and additional data is requested.
    b)If the size of the transferred data exceeds the size of the receiving data item (or the portion of the receiving data item not yet occupied by transferred data), only the leftmost characters of the transferred data are stored in the receiving data item (or in the portion remaining). The remaining characters of the transferred data that do not fit into the receiving data item are ignored. If identifier-1 references a zero-length item, all the characters of the transferred data are ignored.
    5)The implementor shall specify the device that is used if the FROM phrase is not specified.
    

    And My Map of the working storage on IBM Z cobol says pic 99v99 is 4 bytes .

    I still think it is up to the programmer to edit any entered ACCEPT data.

     

    Last edit: Mickey White 2 days ago
    • Michael Del Solio

      I agree that ISO COBOL leaves the conversion between the input device and the data item up to the implementor.

      However, the GnuCOBOL Programmer’s Guide seems to be quite clear about how GnuCOBOL handles this case. For ACCEPT FROM CONSOLE into a numeric field, it says that the input is parsed according to the rules of NUMVAL.

      So I don’t think this is necessarily an ISO COBOL issue. My point is that the current behaviour seems to be different from what the GnuCOBOL documentation describes.

      If 12.99 becoming 12.90 is actually the intended behaviour for a PIC 9(2)V99 field, then I think the Programmer’s Guide should at least be clarified.

       
      • Vincent (Bryan) Coen

        Can you retest this by using pic 99v999 and see if you then get 2
        decimal places - IF so there is a bug in the compiler but I suspect
        there is one already :)
        .

        On 14/08/2026 08:55, Michael Del Solio wrote:

        I agree that ISO COBOL leaves the conversion between the input device
        and the data item up to the implementor.

        However, the GnuCOBOL Programmer’s Guide seems to be quite clear about
        how GnuCOBOL handles this case. For ACCEPT FROM CONSOLE into a numeric
        field, it says that the input is parsed according to the rules of NUMVAL.

        So I don’t think this is necessarily an ISO COBOL issue. My point is
        that the current behaviour seems to be different from what the
        GnuCOBOL documentation describes.

        If 12.99 becoming 12.90 is actually the intended behaviour for a PIC
        9(2)V99 field, then I think the Programmer’s Guide should at least be
        clarified.

         
        • Mickey White

          Mickey White - 1 day ago

          It will work because 99v999 is 5 bytes, but it will drop the last byte when moving to pic 99.99 . I do not think it is a bug, 4 bytes is 4 bytes.

           
  • Giancarlo Canini

    The real problem isn't the floating point, but the complete control of numeric input (length and allowed characters).
    To answer the initial question, as Chuck Haatvedt rightly pointed out, "The ACCEPT statement has NO editing functionality," and to solve the problem, I would propose a more robust solution that allows us to control both the number of characters and the type entered, using a mask in the screen section.

     
    • Vincent (Bryan) Coen

      Normally for accepting numbers that include a decimal place it is
      written as pic 99.99.

      That way the period is shown on screen.

      Option two is ask Chuck for his routine ACCEPT_NUMERIC.c

      Vincent

      On 14/08/2026 16:27, Giancarlo Canini wrote:

      The real problem isn't the floating point, but the complete control of
      numeric input (length and allowed characters).
      To answer the initial question, as Chuck Haatvedt rightly pointed out,
      "The ACCEPT statement has NO editing functionality," and to solve the
      problem, I would propose a more robust solution that allows us to
      control both the number of characters and the type entered, using a
      mask in the screen section.

      Attachments:

       
      👍
      1
      • Giancarlo Canini

        Giancarlo Canini - 20 hours ago

        Of course, you have to use 99.99 as in this example, but the version from the previous post is better; that’s because the SCREEN SECTION gives us greater control over the user's numeric input—and, above all, over the number of digits entered (which is the most important thing for a COBOL programmer)

           IDENTIFICATION DIVISION.
           PROGRAM-ID. PRICE.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
           77  WS-QUANTITY        PIC 9(2).
           77  WS-UNIT-PRICE      PIC 9(2).99.
           77  WS-UNIT-PRICE-CALC PIC 9(2)V99.
           77  WS-TOTAL-PRICE     PIC 9(4)V99.
           77  WS-TOTAL-OUT       PIC ZZZ9.99.
           PROCEDURE DIVISION.
               DISPLAY "Price calculation"
               DISPLAY "Please enter quantity: " WITH NO ADVANCING
               ACCEPT WS-QUANTITY
               DISPLAY "Please enter unit price: " WITH NO ADVANCING
               ACCEPT WS-UNIT-PRICE
        
               MOVE WS-UNIT-PRICE TO WS-UNIT-PRICE-CALC
        
               MULTIPLY WS-QUANTITY BY WS-UNIT-PRICE-CALC
                   GIVING WS-TOTAL-PRICE
        
               MOVE WS-TOTAL-PRICE TO WS-TOTAL-OUT
        
               DISPLAY "Quantity: " WS-QUANTITY
               DISPLAY "Unit price: " WS-UNIT-PRICE
               DISPLAY "The total price is: " WS-TOTAL-OUT
        
               STOP RUN.
        
         

        Last edit: Giancarlo Canini 20 hours ago

Log in to post a comment.