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 変数-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 で書いた場合 ----
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 句で丸め方を指定できます。指定しない場合は切り捨てになります。
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 |
* 銀行家の丸め(統計・金融計算での偏り防止)
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 句で明示してください。また旧バージョンのコンパイラは HALF-UP のみ対応の場合があります。
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
除数が 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
浮動小数点は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:受け取り変数の桁数不足
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 なしで小数が切り捨てられる
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:コードブロックのインデント
* 列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.
よくある質問
ON SIZE ERROR 句が実行されます。ON SIZE ERROR を書いていない場合の動作はコンパイラ依存(プログラム異常終了・ゴミ値格納など)です。ゼロ除算が起こりうる箇所では必ず ON SIZE ERROR を記述するか、除算前に除数が ZERO でないことを IF 文でチェックしてください。MOVE はデータをそのまま転送する命令で、算術式は書けません。COMPUTE は算術式の結果を変数に代入します。単純な値のコピーは MOVE、計算が必要な場合は COMPUTE を使います。PERFORM VARYING でループ乗算することもできます。PIC 9)に負の結果を格納しようとすると、値が正に変換されます(符号が無視される)。計算途中で負の値になる可能性がある場合は必ず PIC S9(符号付き)で宣言してください。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文でデータを転送する方法
