基本的な計算はこの4つの命令でOK!
はじめに:COBOLと計算
COBOLは、特に大量のデータを正確に処理する必要があるビジネスアプリケーションで長年使われてきました。その中心的な機能の一つが、数値を扱う計算処理です。金融システムなどで桁数の多い計算を正確に行えることがCOBOLの強みの一つです。
今回は、COBOLで基本的な四則演算(足し算、引き算、掛け算、割り算)を行うための4つの基本的な命令、ADD
、SUBTRACT
、MULTIPLY
、DIVIDE
について学びます。これらの命令はプログラムの処理を記述する 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
文の方が簡潔に書けることもあります。
これで基本的な計算はバッチリですね!次は文字列を操作する方法について学んでいきましょう!
参考情報
より詳細な情報や他のオプションについては、以下のリソースを参照してください。
-
GnuCOBOL Programmer’s Guide – Arithmetic statements: GnuCOBOL(多くの学習環境で使われるオープンソースのCOBOLコンパイラ)の公式マニュアル。各算術文の詳細な構文とオプションが説明されています。
https://gnucobol.sourceforge.io/doc/gnucobol.html#Arithmetic-statements
-
COBOL入門サイト – 計算処理: 日本語でCOBOLの計算処理(算術文やCOMPUTE文)について解説しているサイト。基本的な使い方や注意点がまとめられています。
https://www.cobol.jp/dictionary/ (COMPUTE文や各算術文のページを参照)
-
MainframesTechHelp – COBOL Arithmetic Statements: 英語ですが、各算術文の構文と簡単な例が紹介されています。
https://www.mainframestechhelp.com/tutorials/cobol/cobol-arithmetic-statements.htm