[COBOLのはじめ方] Part11: 算術演算(ADD, SUBTRACT, MULTIPLY, DIVIDE)

基本的な計算はこの4つの命令でOK!

はじめに:COBOLと計算

COBOLは、特に大量のデータを正確に処理する必要があるビジネスアプリケーションで長年使われてきました。その中心的な機能の一つが、数値を扱う計算処理です。金融システムなどで桁数の多い計算を正確に行えることがCOBOLの強みの一つです。

今回は、COBOLで基本的な四則演算(足し算、引き算、掛け算、割り算)を行うための4つの基本的な命令、ADDSUBTRACTMULTIPLYDIVIDEについて学びます。これらの命令はプログラムの処理を記述する PROCEDURE DIVISION 内で使用します。

COBOLにはこれらの専用命令の他に、COMPUTE文を使って数式のような形式で計算を記述する方法もありますが、今回は基本的な4つの算術文に焦点を当てます。

足し算:ADD命令

ADD命令は、数値データを加算するために使用します。主に2つの書き方があります。

構文

パターン1: 複数の数値を1つの項目に加算 (TO)

ADD {数値リテラル | データ項目1} ... TO {データ項目2}...
    [ROUNDED]
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-ADD]

この形式では、TO の前に指定された数値(リテラルまたはデータ項目の値)が、TO の後に指定された各データ項目に加算されます。結果は TO の後のデータ項目に格納されます。

パターン2: 複数の数値を加算し、結果を別の項目に格納 (GIVING)

ADD {数値リテラル | データ項目1} ... GIVING {データ項目3}...
    [ROUNDED]
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-ADD]

この形式では、GIVING の前に指定された数値(リテラルまたはデータ項目の値)がすべて加算され、その合計が GIVING の後に指定された各データ項目に格納されます。元のデータ項目の値は変更されません。

オプション

  • ROUNDED: 計算結果を格納する際に、結果格納先の桁数に合わせて四捨五入します。指定しない場合は切り捨てられます。
  • ON SIZE ERROR: 計算結果が結果格納先のデータ項目の桁数を超えてしまう(桁あふれ)場合に実行する処理を記述します。
  • NOT ON SIZE ERROR: 桁あふれが発生しなかった場合に実行する処理を記述します。
  • END-ADD: ADD文の終わりを明示的に示します。記述がなくても動作しますが、プログラムの可読性を高めるために推奨されることがあります。

サンプルコード

IDENTIFICATION DIVISION.
PROGRAM-ID. ADD-SAMPLE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 NUM1    PIC 9(3) VALUE 100.
01 NUM2    PIC 9(3) VALUE 50.
01 RESULT1 PIC 9(4) VALUE 0.
01 RESULT2 PIC 9(4) VALUE 0.
PROCEDURE DIVISION.
*   NUM1 に 50 を加算 (NUM1 は 150 になる)
    ADD 50 TO NUM1.
    DISPLAY "ADD TO   : " NUM1.

*   NUM1(150) と NUM2(50) を加算し、RESULT1 に格納 (RESULT1 は 200 になる)
*   NUM1, NUM2 の値は変わらない
    ADD NUM1 NUM2 GIVING RESULT1.
    DISPLAY "ADD GIVING: " RESULT1.

*   10, 20, 30 を加算し、RESULT2 に格納 (RESULT2 は 60 になる)
    ADD 10 20 30 GIVING RESULT2.
    DISPLAY "ADD GIVING(Literals): " RESULT2.

    STOP RUN.

引き算:SUBTRACT命令

SUBTRACT命令は、数値データから別の数値を減算するために使用します。こちらも主に2つの書き方があります。

構文

パターン1: 1つの項目から複数の数値を減算 (FROM)

SUBTRACT {数値リテラル | データ項目1} ... FROM {データ項目2}...
    [ROUNDED]
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-SUBTRACT]

FROM の後に指定された各データ項目から、FROM の前に指定された数値(リテラルまたはデータ項目の値)の合計が減算されます。結果は FROM の後のデータ項目に格納されます。

パターン2: ある数値から別の数値を減算し、結果を別の項目に格納 (GIVING)

SUBTRACT {数値リテラル | データ項目1} ... FROM {数値リテラル | データ項目2}
    GIVING {データ項目3}...
    [ROUNDED]
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-SUBTRACT]

FROM の後に指定された数値から、FROM の前に指定された数値の合計が減算され、その結果が GIVING の後に指定された各データ項目に格納されます。元のデータ項目の値は変更されません。

オプション

ADD命令と同様に、ROUNDED, ON SIZE ERROR, NOT ON SIZE ERROR, END-SUBTRACT が使用できます。

サンプルコード

IDENTIFICATION DIVISION.
PROGRAM-ID. SUBTRACT-SAMPLE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 NUM1    PIC 9(3) VALUE 200.
01 NUM2    PIC 9(3) VALUE 50.
01 RESULT1 PIC S9(4) VALUE 0.  *> 結果が負になる可能性があるので符号(S)を付与
01 RESULT2 PIC S9(4) VALUE 0.
PROCEDURE DIVISION.
*   NUM1 から 30 を減算 (NUM1 は 170 になる)
    SUBTRACT 30 FROM NUM1.
    DISPLAY "SUBTRACT FROM: " NUM1.

*   NUM1(170) から NUM2(50) と 20 を減算し、RESULT1 に格納 (RESULT1 は 100 になる)
*   NUM1 の値は変わらない
    SUBTRACT NUM2 20 FROM NUM1 GIVING RESULT1.
    DISPLAY "SUBTRACT GIVING: " RESULT1.

*   100 から 10, 20, 30 を減算し、RESULT2 に格納 (RESULT2 は 40 になる)
    SUBTRACT 10 20 30 FROM 100 GIVING RESULT2.
    DISPLAY "SUBTRACT GIVING(Literals): " RESULT2.

    STOP RUN.
注意点 : 結果がマイナスになる可能性がある場合は、PIC句に符号(S)をつけましょう (例: PIC S9(4))。符号がない項目に負の値が格納されると、意図しない結果になる可能性があります。

掛け算:MULTIPLY命令

MULTIPLY命令は、数値データを乗算するために使用します。

構文

パターン1: ある項目に数値を乗算 (BY)

MULTIPLY {数値リテラル | データ項目1} BY {データ項目2}...
    [ROUNDED]
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-MULTIPLY]

BY の後に指定された各データ項目に、BY の前に指定された数値(リテラルまたはデータ項目の値)が乗算されます。結果は BY の後のデータ項目に格納されます。

パターン2: 2つの数値を乗算し、結果を別の項目に格納 (GIVING)

MULTIPLY {数値リテラル | データ項目1} BY {数値リテラル | データ項目2}
    GIVING {データ項目3}...
    [ROUNDED]
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-MULTIPLY]

BY の前に指定された数値と、BY の後に指定された数値を乗算し、その結果が GIVING の後に指定された各データ項目に格納されます。元のデータ項目の値は変更されません。

オプション

ADD命令と同様に、ROUNDED, ON SIZE ERROR, NOT ON SIZE ERROR, END-MULTIPLY が使用できます。

サンプルコード

IDENTIFICATION DIVISION.
PROGRAM-ID. MULTIPLY-SAMPLE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 NUM1    PIC 9(3) VALUE 10.
01 NUM2    PIC 9(3) VALUE 5.
01 RESULT1 PIC 9(5) VALUE 0. *> 結果の桁数に注意
01 RESULT2 PIC 9(5) VALUE 0.
PROCEDURE DIVISION.
*   NUM1 に 3 を乗算 (NUM1 は 30 になる)
    MULTIPLY 3 BY NUM1.
    DISPLAY "MULTIPLY BY: " NUM1.

*   NUM1(30) と NUM2(5) を乗算し、RESULT1 に格納 (RESULT1 は 150 になる)
*   NUM1, NUM2 の値は変わらない
    MULTIPLY NUM1 BY NUM2 GIVING RESULT1.
    DISPLAY "MULTIPLY GIVING: " RESULT1.

*   15 と 7 を乗算し、RESULT2 に格納 (RESULT2 は 105 になる)
    MULTIPLY 15 BY 7 GIVING RESULT2.
    DISPLAY "MULTIPLY GIVING(Literals): " RESULT2.

    STOP RUN.
注意点 : 掛け算では結果の桁数が大きくなることがあります。PIC句で十分な桁数を確保しないと桁あふれ(SIZE ERROR)が発生する可能性があります。桁あふれが発生した場合、ON SIZE ERROR句を指定していないと、予期しない結果になったり、プログラムが異常終了したりすることがあります。

割り算:DIVIDE命令

DIVIDE命令は、数値データを除算するために使用します。割り算は少し複雑で、商(結果)だけでなく剰余(余り)を扱うこともできます。

構文

パターン1: ある項目を数値で除算(商を格納)(INTO)

DIVIDE {数値リテラル | データ項目1} INTO {データ項目2}...
    [ROUNDED]
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-DIVIDE]

INTO の後に指定された各データ項目を、INTO の前に指定された数値(リテラルまたはデータ項目の値)で除算します。結果(商)は INTO の後のデータ項目に格納されます。

パターン2: ある数値を別の数値で除算し、商を格納 (BY … GIVING)

DIVIDE {数値リテラル | データ項目1} BY {数値リテラル | データ項目2}
    GIVING {データ項目3}...
    [ROUNDED]
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-DIVIDE]

BY の前に指定された数値を、BY の後に指定された数値で除算し、その結果(商)が GIVING の後に指定された各データ項目に格納されます。

パターン3: 商と剰余の両方を取得 (REMAINDER)

DIVIDE {数値リテラル | データ項目1} BY {数値リテラル | データ項目2}
    GIVING {データ項目3} [ROUNDED] REMAINDER {データ項目4}
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-DIVIDE]

または

DIVIDE {数値リテラル | データ項目1} INTO {数値リテラル | データ項目2}
    GIVING {データ項目3} [ROUNDED] REMAINDER {データ項目4}
    [ON SIZE ERROR 無条件文1]
    [NOT ON SIZE ERROR 無条件文2]
[END-DIVIDE]

GIVING句で商を、REMAINDER句で剰余(余り)をそれぞれ指定したデータ項目に格納します。REMAINDER を使う場合は、GIVING も同時に指定する必要があります。

オプション

ADD命令と同様に、ROUNDED, ON SIZE ERROR, NOT ON SIZE ERROR, END-DIVIDE が使用できます。ROUNDED は商に対してのみ有効です。剰余は四捨五入されません。

サンプルコード

IDENTIFICATION DIVISION.
PROGRAM-ID. DIVIDE-SAMPLE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 NUM1     PIC 9(5) VALUE 100.
01 NUM2     PIC 9(3) VALUE 8.
01 WK-NUM   PIC 9(5) VALUE 50.
01 SHOU     PIC 9(5)V99 VALUE 0. *> 商 (小数点以下も考慮)
01 SHOU-INT PIC 9(5)    VALUE 0. *> 商 (整数部のみ)
01 JOYO     PIC 9(3)    VALUE 0. *> 剰余
PROCEDURE DIVISION.
*   WK-NUM(50) を 2 で除算 (WK-NUM は 25 になる)
    DIVIDE 2 INTO WK-NUM.
    DISPLAY "DIVIDE INTO: " WK-NUM.

*   NUM1(100) を NUM2(8) で除算し、商を SHOU に格納
*   (SHOU は 12.50 になる)
    DIVIDE NUM1 BY NUM2 GIVING SHOU.
    DISPLAY "DIVIDE BY GIVING (Decimal): " SHOU.

*   100 を 8 で除算し、商(整数)を SHOU-INT に、剰余を JOYO に格納
*   (SHOU-INT は 12, JOYO は 4 になる)
    DIVIDE 100 BY 8 GIVING SHOU-INT REMAINDER JOYO.
    DISPLAY "DIVIDE BY GIVING/REMAINDER:".
    DISPLAY "  SHOU(Integer): " SHOU-INT.
    DISPLAY "  JOYO(Remainder): " JOYO.

    STOP RUN.
注意点 :
  • ゼロ除算: 0で割ることはできません。実行時エラー(またはON SIZE ERRORが発生)となるため、事前に割る数が0でないかチェックするなどの対応が必要です。
  • 商の小数点: 割り切れない場合、商を格納する項目のPIC句で小数点(V)を指定しないと、小数点以下は切り捨てられます。ROUNDEDを指定すると四捨五入されます。
  • 剰余: REMAINDERで得られる剰余の計算方法は、商の計算方法(切り捨てか四捨五入か)に依存する場合があります。剰余は常に整数として計算されます。
  • 桁あふれ: 商が結果格納項目の桁数を超えた場合にON SIZE ERRORが発生します。剰余の桁あふれはチェックされません。

まとめと補足

今回はCOBOLの基本的な算術演算命令 ADD, SUBTRACT, MULTIPLY, DIVIDE を学びました。

命令 意味 主な構文パターン
ADD 足し算 ADD A TO B.
ADD A B GIVING C.
SUBTRACT 引き算 SUBTRACT A FROM B.
SUBTRACT A FROM B GIVING C.
MULTIPLY 掛け算 MULTIPLY A BY B.
MULTIPLY A BY B GIVING C.
DIVIDE 割り算 DIVIDE A INTO B.
DIVIDE A BY B GIVING C [REMAINDER D].

GIVING句を使うと、元の変数の値を変更せずに計算結果を別の変数に格納できるため、多くの場面で役立ちます 。

計算を行う上で最も重要なことの一つは、データ定義(PIC句)です。

  • 結果を格納する変数の桁数が十分か?(桁あふれ ON SIZE ERROR に注意)
  • 結果がマイナスになる可能性はあるか?(符号 S の指定)
  • 小数点以下の計算が必要か?(小数点 V と桁数の指定)
  • 計算結果を四捨五入するか、切り捨てるか?(ROUNDED 句の指定)

これらを考慮してデータ項目を定義し、適切な演算命令を選択することが、正確な計算処理を行うための鍵となります。

また、COBOLにはCOMPUTE文という、より数式に近い形で計算を記述できる命令もあります。複雑な計算を行う場合はCOMPUTE文の方が簡潔に書けることもあります。

これで基本的な計算はバッチリですね!次は文字列を操作する方法について学んでいきましょう!

参考情報

より詳細な情報や他のオプションについては、以下のリソースを参照してください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です