Search code examples
cobolmultiplication

MULTIPLY doesn't behave as I would expect


I have this cobol program, meant to calculate a factorial:

   IDENTIFICATION DIVISION.
   PROGRAM-ID. Factorial-hopefully.
   AUTHOR. Darth Egregious.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01 Keeping-Track-Variables.
      05 Operand                      PIC S99   VALUE 0.
      05 Product                      PIC S99   VALUE 1.
   PROCEDURE DIVISION.
   PERFORM-FACTORIAL.
    DISPLAY SPACES
    PERFORM VARYING Operand FROM 6 BY -1 UNTIL Operand = 0

      DISPLAY "Before Product " Product " Operand " Operand
      MULTIPLY Product By Operand GIVING Product
      DISPLAY "After Product " Product " Operand " Operand
    END-PERFORM
    DISPLAY Product.
   STOP RUN.

I run it like this:

cobc -free -x -o a.out fact.cbl && ./a.out

And I get this strange output:

Before Product +01 Operand +06
After Product +06 Operand +06
Before Product +06 Operand +05
After Product +30 Operand +05
Before Product +30 Operand +04
After Product +30 Operand +04
Before Product +30 Operand +03
After Product +90 Operand +03
Before Product +90 Operand +02
After Product +90 Operand +02
Before Product +90 Operand +01
After Product +90 Operand +01
+90

My decrementing loop is working as expected, but the MULTIPLY command is behaving strangely. It's doing 1*6, and 6*5 correctly, but 30*4 doesn't seem to work, then 30*3 does, and finally 90*2 doesn't work again. Does COBOL not like multiplying by powers of two or something?


Solution

  • My decrementing loop is working as expected, but the MULTIPLY command is behaving strangely. It's doing 1*6, and 6*5 correctly, but 30*4 doesn't seem to work, then 30*3 does, and finally 90*2 doesn't work again. Does COBOL not like multiplying by powers of two or something?

      05 Operand                      PIC S99   VALUE 0.
      05 Product                      PIC S99   VALUE 1.
    

    When you are multiplying 30*4 and 90*2, the values are larger than the PICTURE clause, S99.

    Increase the size of the PIC clause to, say, S999.


    Response to comments:

    Technically, the result is undefined [COBOL 85], therefore doing nothing is a valid choice. Other implementations will truncate the value giving a different result.

    So it isn't so much the language as it is the implementation.

    The language also allows the SIZE ERROR phrase to catch truncation errors. In that situation, the result is unaltered, but additional code may be executed to indicate that the error occurred.

    With COBOL 2002, the result is defined by the implementor, if the ON SIZE ERROR phrase isn't specified and checking of the EC-SIZE-TRUNCATION exception is not active.


    Quote from 2002 standard:

    F.1 Substantive changes potentially affecting existing programs

    15) Size error condition with no SIZE ERROR phrase. If a size error condition occurs, the statement in which it occurs contains no SIZE ERROR or NOT SIZE ERROR phrase, and there is no associated declarative, the implementor defines whether the run unit is terminated or execution continues with incorrect values.

    Justification:

    In the previous COBOL standard, the rules for size error stated that execution would continue with undefined values, but it was not clear where execution would continue, particularly in conditional statements. Additionally, continued execution with incorrect results was not acceptable for many critical applications, where it might cause corruption of databases, incorrect continued execution of the program, and potentially a multitude of additional errors. It was prohibitive to modify programs to add ON SIZE ERROR for every affected statement. Responding to user requirements, several implementors terminated execution of the program in this situation; in some cases, the implementor allowed selection of termination based on a compiler directive.

    The number and criticality of applications that terminated in this situation provides strong justification for this change. It is expected that this change will have little impact on existing programs because implementors are free to continue or terminate, in accordance with their implementation of the previous COBOL standard.