COBOLおよび$ 2,020 202.02

過去数年、ここ1、2年でさえ、誰かが2,020,202ドル...と02セントのばかげた金額の請求書または小切手を受け取ったというニュースに時々出くわしました。



これが表示された場合、それは(ほぼ確実に)COBOLプログラミングエラーです。ほとんどのCOBOLプログラマーはこのばかげた間違いを犯しますが、私も例外ではありません。



この問題は、通常レコードを初期化する方法が原因で発生します。このような小さなプログラムを見てみましょう:



       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.


このプログラムでは、入力レコードdr-datarec通常はディスク上のどこかから取得されますが、この簡単なテストでは手動で作成されます。



入力レコードを受信すると、計算が実行され、を使用してレコードが出力されますdt-detail



問題は、レコードがどのように作成されるかですdr-datarecスペースを移動して初期化する方法に注目してください。これは、レコードを初期化するための一般的な方法でした。



したがって、PIC Xのすべてのフィールドにスペースがあります。しかし!すべてのCOMP-3フィールドも初期化されますが、ゼロにはなりません。プログラマーは、すべてのCOMP-3フィールドに対して有効な値が生成されていることを確認する必要があります。テストプログラムはそれを正しく行います:



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


フィールドにはdr-amount明らかに100があります。開始後、次のことがわかります。



./mistake 
test                       100.00


エンコードエラーがあり、レコードがdr-amount正しく初期化されていない場合はどうなりますか?



そこにはまだASCIIスペースがあります。これは、16の値20またはバイナリ0010 0000です



。COMP-3は桁を4ビットのニブルとして格納するため、1つのスペースは20として表示されます。dr-amountのように9桁の場合、これには10個のメモリニブル(9個のニブル)が必要です。数字の場合は1つ、符号の場合は1つ)または5バイト。



スペースを移動するdr-datarecと、このフィールドに5つのスペースまたは16進値2020202020が格納されます。初期化されていない変数を使用しようとすると、2020202.02として解釈されます。



初期化をコメントアウトすると、dr-amount次のエラーを強制できます。



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


プログラムを開始するとき:



./mistake 
test                 2,020,202.02


この問題を修正するために、COBOL85ではINITIALIZE動詞が導入されました。スペースをレコードに移動する代わりに、レコードを初期化すると、スペースが英数字フィールドに移動し、ゼロが数値フィールドに移動します。



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


実行結果:



./mistake 
test                         0.00


したがって、次に2,020,202.02ドルの公共料金を受け取った貧しい未亡人を見ると、何が起こったのかが正確にわかります。



All Articles