COBOL y $ 2,020 202.02

En los últimos años, incluso en el último año o dos, a veces me encontré con la noticia de que alguien recibió una factura o un cheque por una cantidad ridícula de 2.020.202 dólares ... y 02 centavos.



Si ve esto, es (casi con seguridad) un error de programación COBOL. La mayoría de los programadores de COBOL cometen este estúpido error y yo no soy una excepción.



El problema se debe a la forma en que normalmente inicializamos el registro. Tomemos un pequeño programa como este:



       identification division.
       program-id.
           mistake.
       
       data division.
       working-storage section.
      
      * *** Input record, typically maintained on disk/tape somewhere.
       01  dr-datarec.
           03  dr-name                 pic x(20).
           03  dr-amount               pic s9(7)v99, comp-3.

      * *** print record, sent to a line printer.
       01  dt-detail.
           03  dt-name                 pic x(20).
           03  filler                  pic x.
           03  dt-amount               pic z,zzz,zz9.99.            
       
       procedure division.
       
           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
           move 100                    to dr-amount.

           move spaces                 to dt-detail.
           move dr-name                to dt-name.
           move dr-amount              to dt-amount.

           display dt-detail.
       
           stop run.


En este programa, el registro de entrada dr-datarec. Por lo general, proviene de algún lugar del disco, pero para esta simple prueba se crea manualmente.



Una vez que se recibe un registro de entrada, se realiza el cálculo y luego el registro se envía utilizando dt-detail.



El problema es cómo se crea el registro dr-datarec. Observe cómo se mueven los espacios para inicializarlo. Este era el método típico para inicializar un registro.



Por lo tanto, hay espacios en todos los campos PIC X. ¡Pero! Todos los campos COMP-3 también se inicializan, pero no a cero. El programador debe asegurarse de que se generen valores válidos para todos los campos COMP-3. El programa de prueba lo hace bien:



           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
           move 100                    to dr-amount.


dr-amountClaramente hay 100 en el campo. Después de comenzar, resulta:



./mistake 
test                       100.00


¿Qué pasa si hay un error de codificación y el registro dr-amountno se inicializa correctamente?



Todavía hay espacios ASCII allí. Este es un valor hexadecimal de 20 o binario 0010 0000.



COMP-3 almacena dígitos como nibbles de cuatro bits, por lo que un espacio se muestra como 20. Si tiene 9 dígitos como dr-amount, entonces esto requiere 10 nibbles de memoria (9 nibbles para dígitos y uno para signo) o 5 bytes.



Al mover espacios, dr-datarecse almacenarán 5 espacios o el valor hexadecimal 2020202020 en este campo. Si intenta utilizar una variable no inicializada, se interpretará como 2020202.02.



Si comenta la inicialización dr-amount, puede forzar este error:



           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
     *     move 100                    to dr-amount.


Ahora al iniciar el programa:



./mistake 
test                 2,020,202.02


Para solucionar este problema, COBOL 85 introdujo el verbo INICIALIZAR. En lugar de mover espacios a un registro, lo inicializa y moverá espacios a campos alfanuméricos y ceros a campos numéricos:



      *    move spaces                 to dr-datarec.
           initialize dt-detail.
           move "test"                 to dr-name.
      *    move 100                    to dr-amount.


Resultado de ejecución:



./mistake 
test                         0.00


Entonces, la próxima vez que vea a una viuda pobre que recibió una factura de servicios públicos de $ 2,020,202.02, ¡sabrá exactamente qué sucedió!



All Articles