【COBOL】COMPUTEで計算を行う|演算子・ROUNDED・ON SIZE ERROR・実践パターン完全ガイド

COBOLで数値計算を行うとき、最もよく使われるのが COMPUTE 文です。加算・減算・乗算・除算・べき乗を1行の式で記述でき、ADD/SUBTRACT/MULTIPLY/DIVIDE といった個別の算術文より複雑な計算を読みやすく書けます。

本記事では基本構文から、ROUNDED句のモード詳細、オーバーフロー時のエラーハンドリング(ON SIZE ERROR)、データ型の選び方、消費税計算・給与計算・複利計算などの実践パターンまで、COMPUTE文のすべてを解説します。

この記事でわかること

  • COMPUTE文の基本構文と演算子の優先順位
  • COMPUTE vs ADD/SUBTRACT/MULTIPLY/DIVIDE の使い分け
  • ROUNDED句の効果とROUNDINGモードの種類
  • ON SIZE ERROR / NOT ON SIZE ERROR によるオーバーフロー対策
  • 複数変数への同時代入パターン
  • データ型(COMP-3・COMP)と計算精度の関係
  • 消費税計算・給与計算・複利計算など実践パターン
スポンサーリンク

COMPUTE文の基本構文

COMPUTE文は算術式の結果を1つ以上の変数に代入します。

COMPUTE文の基本構文
       COMPUTE 変数-1 [ROUNDED] [変数-2 [ROUNDED] ...]
           = 算術式
           [ON SIZE ERROR 命令文]
           [NOT ON SIZE ERROR 命令文]
       END-COMPUTE
シンプルな例
       WORKING-STORAGE SECTION.
       01  WS-NUM1     PIC 9(5)    VALUE 12000.
       01  WS-NUM2     PIC 9(5)    VALUE  3500.
       01  WS-RESULT   PIC 9(6).

       PROCEDURE DIVISION.
           COMPUTE WS-RESULT = WS-NUM1 + WS-NUM2
           DISPLAY "合計: " WS-RESULT
           STOP RUN.

演算子の種類と優先順位

COMPUTE文で使える演算子は5種類です。優先順位が高いものから実行されます。

優先順位 演算子 意味
1(最高) ** べき乗 2 ** 8 → 256
2 単項 - 符号反転 -WS-A
3 * / 乗算・除算 A * B / C
4(最低) + - 加算・減算 A + B - C
演算子と優先順位の例
       01  WS-A  PIC 9(3) VALUE 10.
       01  WS-B  PIC 9(3) VALUE  3.
       01  WS-C  PIC 9(3) VALUE  2.
       01  WS-R  PIC 9(6).

       * べき乗は最初に評価される
       COMPUTE WS-R = WS-A + WS-B ** WS-C
       * = 10 + (3 ** 2) = 10 + 9 = 19

       * 括弧で優先順位を変更
       COMPUTE WS-R = (WS-A + WS-B) ** WS-C
       * = (10 + 3) ** 2 = 13 ** 2 = 169

       * 複雑な式も1行で記述できる
       COMPUTE WS-R = WS-A * WS-B + WS-C * 4 - 1
       * = (10 * 3) + (2 * 4) - 1 = 30 + 8 - 1 = 37

COMPUTE vs 個別算術文(ADD / SUBTRACT / MULTIPLY / DIVIDE)

COBOLには COMPUTE のほかに加算専用の ADD、除算専用の DIVIDE などの個別算術文があります。どちらを使うべきかの判断基準をまとめます。

観点 COMPUTE 個別算術文(ADD等)
複雑な式 ◎(1行で記述可) △(複数行が必要)
可読性(単純計算) ◎(意図が明確)
REMAINDER(余り) ×(取得不可) ○(DIVIDEのみ)
CORRESPONDING × ○(ADD/SUBTRACTのみ)
カウントアップ COMPUTE X = X + 1 ADD 1 TO X
同じ計算の COMPUTE vs 個別算術文 比較
       * ---- COMPUTE で書いた場合 ----
       COMPUTE WS-TAX-AMOUNT
           = WS-PRICE * WS-TAX-RATE / 100

       * ---- 個別算術文で書いた場合 ----
       MULTIPLY WS-PRICE BY WS-TAX-RATE
           GIVING WS-WORK
       DIVIDE 100 INTO WS-WORK
           GIVING WS-TAX-AMOUNT

       * 複雑な式ほど COMPUTE が有利
       * 余り(REMAINDER)が必要な場合は DIVIDE を使う
       DIVIDE WS-TOTAL BY 3
           GIVING WS-QUOTIENT
           REMAINDER WS-REM
使い分けの基本方針
① 複数の演算子を組み合わせる場合 → COMPUTE
② 単純な1演算(カウントアップ等)→ 個別算術文(ADD 1 TO X 等)
③ 余り(REMAINDER)が必要 → DIVIDE 文を使う(詳細は DIVIDE文の解説

ROUNDED句:小数の丸め処理

計算結果の小数部が受け取り変数の定義桁数を超えるとき、ROUNDED 句で丸め方を指定できます。指定しない場合は切り捨てになります。

ROUNDED の基本
       01  WS-PRICE     PIC 9(5)V99  VALUE 1234.56.
       01  WS-RATE      PIC V99      VALUE .08.
       01  WS-TAX       PIC 9(5)V9.  * 小数1桁
       01  WS-TAX-TRUNC PIC 9(5)V9.  * 比較用

       * ROUNDED なし: 切り捨て
       COMPUTE WS-TAX-TRUNC = WS-PRICE * WS-RATE
       * 1234.56 * 0.08 = 98.7648 → 98.7(切り捨て)

       * ROUNDED あり: 四捨五入(デフォルト = HALF-UP)
       COMPUTE WS-TAX ROUNDED = WS-PRICE * WS-RATE
       * 1234.56 * 0.08 = 98.7648 → 98.8(四捨五入)

ROUNDINGモード(COBOL 2002以降)

COBOL 2002規格以降、ROUNDED の後にモードを指定できます。金融計算では HALF-EVEN(銀行家の丸め)が重要です。

モード 動作 例: 2.5→ 例: 3.5→
HALF-UP(デフォルト) 0.5以上なら切り上げ(四捨五入) 3 4
HALF-EVEN 0.5のとき偶数に丸める(銀行家の丸め) 2 4
HALF-DOWN 0.5以下なら切り捨て 2 3
UP ゼロから離れる方向に切り上げ 3 4
DOWN ゼロに近い方向に切り捨て 2 3
TRUNCATION 常に切り捨て(ROUNDEDなしと同じ) 2 3
ROUNDINGモードの指定(COBOL 2002以降)
       * 銀行家の丸め(統計・金融計算での偏り防止)
       COMPUTE WS-RESULT ROUNDED MODE HALF-EVEN
           = WS-VALUE / WS-DIVISOR

       * 常に切り上げ(請求金額の計算など)
       COMPUTE WS-BILLING ROUNDED MODE UP
           = WS-USAGE * WS-UNIT-PRICE

       * 常に切り捨て(税額計算 → 端数を消費者有利に)
       COMPUTE WS-TAX ROUNDED MODE DOWN
           = WS-SUBTOTAL * WS-TAX-RATE
ROUNDEDなしは常に切り捨て
ROUNDED を指定しないと小数部は切り捨てになります。消費税額の計算など端数処理が重要な場面では、意図した丸め方を ROUNDED 句で明示してください。また旧バージョンのコンパイラは HALF-UP のみ対応の場合があります。

ON SIZE ERROR:オーバーフロー対策

計算結果が受け取り変数に収まらない(桁あふれ)とき、ON SIZE ERROR 句が実行されます。この句を指定しないと、オーバーフロー時に上位桁が欠落して誤った値が格納されます。

ON SIZE ERROR の基本
       01  WS-A       PIC 9(3) VALUE 999.
       01  WS-B       PIC 9(3) VALUE   2.
       01  WS-RESULT  PIC 9(3).  * 最大 999 まで格納可

       COMPUTE WS-RESULT = WS-A * WS-B
           ON SIZE ERROR
               DISPLAY "エラー: 桁あふれが発生しました"
               MOVE ZERO TO WS-RESULT
           NOT ON SIZE ERROR
               DISPLAY "計算結果: " WS-RESULT
       END-COMPUTE
       * 999 * 2 = 1998 → PIC 9(3) に収まらない → ON SIZE ERROR 実行
エラーフラグを使った本格的なエラーハンドリング
       01  WS-CALC-ERROR-FLG  PIC X(1) VALUE "N".
           88  CALC-ERROR     VALUE "Y".
           88  CALC-OK        VALUE "N".
       01  WS-NUMERATOR   PIC S9(7)V99.
       01  WS-DENOMINATOR PIC S9(5)V99.
       01  WS-QUOTIENT    PIC S9(7)V9(4).

       COMPUTE WS-QUOTIENT ROUNDED
           = WS-NUMERATOR / WS-DENOMINATOR
           ON SIZE ERROR
               SET CALC-ERROR TO TRUE
               DISPLAY "SIZE ERROR: " WS-NUMERATOR
                       " / " WS-DENOMINATOR
           NOT ON SIZE ERROR
               SET CALC-OK TO TRUE
       END-COMPUTE

       IF CALC-ERROR
           PERFORM ERROR-HANDLING-PARA
       END-IF
ゼロ除算も SIZE ERROR になる
除数が 0 の場合も ON SIZE ERROR が発火します。ゼロ除算を個別にチェックしたい場合は、COMPUTE の前に IF WS-DENOMINATOR = ZERO で分岐させてください。

複数変数への同時代入

COMPUTE文では複数の変数に同じ計算結果をまとめて代入できます。

複数変数への同時代入
       01  WS-TOTAL-A    PIC 9(8).
       01  WS-TOTAL-B    PIC 9(8).
       01  WS-TOTAL-DISP PIC Z(7)9.
       01  WS-BASE       PIC 9(5) VALUE 15000.
       01  WS-RATE       PIC 9(3) VALUE 110.

       * 3つの変数に同じ値を同時に代入
       COMPUTE WS-TOTAL-A
               WS-TOTAL-B
               WS-TOTAL-DISP
           = WS-BASE * WS-RATE / 100
       * → WS-TOTAL-A = WS-TOTAL-B = WS-TOTAL-DISP = 16500

       * 各変数に個別のROUNDEDを指定することも可能
       COMPUTE WS-TOTAL-A ROUNDED
               WS-TOTAL-B
           = WS-BASE * WS-RATE / 100

データ型と計算精度

COBOLの数値型によって計算速度・精度・用途が変わります。COMPUTE文を使う際に適切なデータ型を選ぶことが重要です。

宣言方法 内部表現 用途 備考
PIC 9(n) ゾーン10進数(文字列) 表示・入出力 計算は遅め
PIC 9(n) COMP-3 パック10進数 業務計算(金額・数量) ◎ 精度高・計算速い
PIC 9(n) COMP 2進数(整数) カウンタ・添え字 ◎ 整数演算に最速
COMP-1 単精度浮動小数点 科学計算 金融計算には不向き
COMP-2 倍精度浮動小数点 科学計算 金融計算には不向き
業務計算での推奨データ型
       * 金額計算には COMP-3(パック10進数)が推奨
       01  WS-PRICE       PIC S9(7)V99  COMP-3.
       01  WS-QTY         PIC S9(5)     COMP-3.
       01  WS-TAX-RATE    PIC V9(4)     COMP-3  VALUE .1000.
       01  WS-SUBTOTAL    PIC S9(9)V99  COMP-3.
       01  WS-TAX         PIC S9(7)V99  COMP-3.
       01  WS-TOTAL       PIC S9(9)V99  COMP-3.

       COMPUTE WS-SUBTOTAL = WS-PRICE * WS-QTY
       COMPUTE WS-TAX ROUNDED
           = WS-SUBTOTAL * WS-TAX-RATE
       COMPUTE WS-TOTAL = WS-SUBTOTAL + WS-TAX
浮動小数点型(COMP-1/COMP-2)は金融計算に使わない
浮動小数点は2進数で小数を表現するため、0.1 や 0.01 などを正確に表現できません。金額・税額・給与などの業務計算には COMP-3(パック10進数)か PIC 9(n)V9(m) を使用してください。

実践パターン集

パターン1:消費税計算(端数処理あり)

消費税計算
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TAXCALC.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-PRICE       PIC S9(7)V99  COMP-3.
       01  WS-TAX-RATE    PIC V99       COMP-3  VALUE .10.
       01  WS-TAX         PIC S9(7)V99  COMP-3.
       01  WS-TOTAL       PIC S9(9)V99  COMP-3.
       01  WS-DISP-TOTAL  PIC ZZZ,ZZZ,ZZ9.

       PROCEDURE DIVISION.
           MOVE 12800.00 TO WS-PRICE

           * 税額を切り捨て(消費者有利)
           COMPUTE WS-TAX ROUNDED MODE DOWN
               = WS-PRICE * WS-TAX-RATE
           * 12800 * 0.10 = 1280.00 → 1280

           COMPUTE WS-TOTAL = WS-PRICE + WS-TAX
           MOVE WS-TOTAL TO WS-DISP-TOTAL
           DISPLAY "税込合計: " WS-DISP-TOTAL
           STOP RUN.

パターン2:給与計算(残業代・控除)

基本給・残業代・控除を含む給与計算
       01  WS-BASE-SALARY   PIC S9(7)V99  COMP-3.
       01  WS-HOURLY-RATE   PIC S9(5)V99  COMP-3.
       01  WS-OVERTIME-HRS  PIC S9(3)V9   COMP-3.
       01  WS-OVERTIME-PAY  PIC S9(7)V99  COMP-3.
       01  WS-HEALTH-INS    PIC S9(7)V99  COMP-3.
       01  WS-PENSION       PIC S9(7)V99  COMP-3.
       01  WS-GROSS         PIC S9(8)V99  COMP-3.
       01  WS-NET           PIC S9(8)V99  COMP-3.

           * 残業代 = 時給 × 残業時間 × 1.25(時間外割増)
           COMPUTE WS-OVERTIME-PAY ROUNDED MODE DOWN
               = WS-HOURLY-RATE * WS-OVERTIME-HRS * 1.25

           * 総支給額
           COMPUTE WS-GROSS
               = WS-BASE-SALARY + WS-OVERTIME-PAY

           * 健康保険料(概算: 総支給の5%)
           COMPUTE WS-HEALTH-INS ROUNDED MODE DOWN
               = WS-GROSS * .05

           * 厚生年金(概算: 総支給の9.15%)
           COMPUTE WS-PENSION ROUNDED MODE DOWN
               = WS-GROSS * .0915

           * 手取り
           COMPUTE WS-NET
               = WS-GROSS - WS-HEALTH-INS - WS-PENSION

パターン3:複利計算

複利計算(元利合計)
       01  WS-PRINCIPAL  PIC S9(9)V99  COMP-3.  * 元金
       01  WS-RATE       PIC V9(4)     COMP-3.  * 年利率
       01  WS-YEARS      PIC 9(3)      COMP.    * 期間(年)
       01  WS-AMOUNT     PIC S9(11)V99 COMP-3.  * 元利合計
       01  WS-WORK       PIC S9(3)V9(4) COMP-3.

           MOVE 1000000.00 TO WS-PRINCIPAL
           MOVE  .0050      TO WS-RATE      * 年利0.50%
           MOVE 10          TO WS-YEARS

           * 元利合計 = 元金 × (1 + 利率) ** 年数
           COMPUTE WS-WORK = 1 + WS-RATE
           COMPUTE WS-AMOUNT ROUNDED
               = WS-PRINCIPAL * WS-WORK ** WS-YEARS
           * 1,000,000 * (1.005 ** 10) ≒ 1,051,140

           DISPLAY "元利合計: " WS-AMOUNT

パターン4:平均・分散計算

データ配列の平均・最大・最小
       01  WS-SCORES.
           05  WS-SCORE   PIC 9(3) OCCURS 5 TIMES.
       01  WS-TOTAL    PIC 9(5)    COMP-3  VALUE ZERO.
       01  WS-AVG      PIC 9(3)V9  COMP-3.
       01  WS-IDX      PIC 9(2)    COMP.

           MOVE 85 TO WS-SCORE(1)
           MOVE 92 TO WS-SCORE(2)
           MOVE 78 TO WS-SCORE(3)
           MOVE 95 TO WS-SCORE(4)
           MOVE 88 TO WS-SCORE(5)

           PERFORM VARYING WS-IDX FROM 1 BY 1
               UNTIL WS-IDX > 5
               COMPUTE WS-TOTAL = WS-TOTAL + WS-SCORE(WS-IDX)
           END-PERFORM

           * 平均を計算(小数1桁、四捨五入)
           COMPUTE WS-AVG ROUNDED
               = WS-TOTAL / 5
           DISPLAY "合計: " WS-TOTAL " 平均: " WS-AVG

よくあるミスとデバッグ

ミス1:受け取り変数の桁数不足

NG:受け取り変数の桁数不足
       01  WS-A    PIC 9(3) VALUE 999.
       01  WS-B    PIC 9(3) VALUE 999.
       01  WS-R    PIC 9(3).  * ← 最大999。999×999=998001は入らない

       COMPUTE WS-R = WS-A * WS-B
       * ON SIZE ERROR なしだと WS-R = 001(上位桁欠落)

       * OK:桁数を十分に確保 + ON SIZE ERROR
       01  WS-R-OK PIC 9(7).  * 余裕を持った桁数
       COMPUTE WS-R-OK = WS-A * WS-B
           ON SIZE ERROR DISPLAY "桁あふれ"
       END-COMPUTE

ミス2:ROUNDED なしで小数が切り捨てられる

NG:税計算でROUNDEDを忘れる
       01  WS-PRICE   PIC 9(5)V99 VALUE 1234.56.
       01  WS-TAX-RT  PIC V99     VALUE .08.
       01  WS-TAX     PIC 9(4)V9.  * 小数1桁

       * NG: ROUNDED なし → 切り捨て
       COMPUTE WS-TAX = WS-PRICE * WS-TAX-RT
       * 98.7648 → 98.7 (切り捨て)

       * OK: ROUNDED あり → 四捨五入
       COMPUTE WS-TAX ROUNDED = WS-PRICE * WS-TAX-RT
       * 98.7648 → 98.8 (四捨五入)

ミス3:コードブロックのインデント

伝統的COBOLのインデントルール
      * 列1-6: 行番号(任意)
      * 列7 : インジケータ(* でコメント行)
      * 列8-11: Area A(DIVISION・SECTION・段落名)
      * 列12-72: Area B(命令文)

      *  1234567890123456789012345678
       PROCEDURE DIVISION.
           COMPUTE WS-RESULT      <- Area B (列12以降)
               = WS-A * WS-B     <- 継続行も Area B
               ON SIZE ERROR
                   DISPLAY "ERROR"
           END-COMPUTE.

よくある質問

QCOMPUTE文でゼロ除算が起きたときはどうなりますか?
Aゼロ除算が発生すると ON SIZE ERROR 句が実行されます。ON SIZE ERROR を書いていない場合の動作はコンパイラ依存(プログラム異常終了・ゴミ値格納など)です。ゼロ除算が起こりうる箇所では必ず ON SIZE ERROR を記述するか、除算前に除数が ZERO でないことを IF 文でチェックしてください。
QCOMPUTE と MOVE の違いは何ですか?
AMOVE はデータをそのまま転送する命令で、算術式は書けません。COMPUTE は算術式の結果を変数に代入します。単純な値のコピーは MOVE、計算が必要な場合は COMPUTE を使います。
Qべき乗(**)はどのコンパイラでも使えますか?
AANSI/ISO COBOL 標準に含まれているため、主要なコンパイラ(IBM COBOL、Micro Focus、OpenCOBOL/GnuCOBOL)では使えます。ただし極めて古い実装では非対応のケースがあります。べき乗の代替として PERFORM VARYING でループ乗算することもできます。
Q符号付き変数(PIC S9)を使わないと何が起きますか?
A符号なし変数(PIC 9)に負の結果を格納しようとすると、値が正に変換されます(符号が無視される)。計算途中で負の値になる可能性がある場合は必ず PIC S9(符号付き)で宣言してください。
QCOMPUTE文を使うときに END-COMPUTE は必須ですか?
AON SIZE ERROR 句や NOT ON SIZE ERROR 句を使う場合は END-COMPUTE でスコープを明示することを強く推奨します。これらの句を使わない単純な COMPUTE では END-COMPUTE は任意ですが、一貫してスコープ終端を書く習慣をつけると読みやすいコードになります。

まとめ

COMPUTE文のポイントをまとめます。

  • 演算子:+ – * / **(べき乗)の5種類。優先順位は ** > 単項- > * / > + –
  • vs 個別算術文:複数演算が絡む場合は COMPUTE が可読性・保守性で優位。余りが必要なら DIVIDE を使う
  • ROUNDED:指定なしは切り捨て。業務要件に合わせて HALF-UP / HALF-EVEN / DOWN 等を選択
  • ON SIZE ERROR:オーバーフロー・ゼロ除算の必須対策。本番コードでは必ず記述する
  • データ型:金額計算には COMP-3(パック10進数)、カウンタには COMP(2進数)が最適

関連記事:DIVIDE文で除算(割り算)を行う方法カウントを数えて表示する方法(ADD/COMPUTE/PERFORM VARYING)COBOLで四捨五入を行う2つの方法MOVE文でデータを転送する方法