COBOLの丸め処理完全ガイド|ROUNDED・6つのROUNDING MODE・消費税/給与/帳票の端数処理実践

COBOLで数値を丸めるとき、何も指定しなければ小数部は切り捨てになります。四捨五入にするには明示的にROUNDEDを指定する必要があり、さらに丸めの方式(四捨五入・偶数丸め・切り上げなど)をROUNDING MODEで選択できます。

業務によって適切な丸め方式は異なります。消費税は「切り捨て」、銀行の利息計算は「偶数丸め」、帳票の集計では「端数の不一致」を起こさない設計が必要です。この記事では丸め方式の選び方から、端数処理の業務パターン、累積誤差の防止策まで解説します。

この記事でわかること

  • ROUNDEDを指定しない場合の動作(暗黙的な切り捨て)
  • 6つの丸めモードと業務別の使い分け基準
  • 消費税計算・給与計算・帳票集計の端数処理パターン
  • FUNCTION ROUND / FUNCTION INTEGER-PART の活用
  • 丸め誤差の累積問題と防止テクニック
  • 端数合計不一致を防ぐ「最終調整方式」の実装
スポンサーリンク

COBOLでROUNDEDを指定しない場合の動作

COBOLで計算結果を変数に格納するとき、受け取り側のPIC句より小数点以下の桁数が多い場合、デフォルトで切り捨て(TRUNCATION)が行われます。これはROUNDEDを指定しない場合の挙動で、意図せず発生することがあります。

暗黙的な切り捨ての例
WORKING-STORAGE SECTION.
01 WS-PRICE     PIC 9(7)V99.    *> 小数2桁
01 WS-RATE      PIC V999.       *> 小数3桁(例: .108 = 10.8%)
01 WS-RESULT-A  PIC 9(7)V99.    *> 小数2桁(受け取り側)
01 WS-RESULT-B  PIC 9(7)V99.

PROCEDURE DIVISION.
    MOVE 12345.00 TO WS-PRICE
    MOVE .108     TO WS-RATE

    *--- ROUNDED指定なし(切り捨て)---
    COMPUTE WS-RESULT-A = WS-PRICE * WS-RATE
    *> 12345 * 0.108 = 1333.26
    *> PIC 9(7)V99に格納 → 小数3桁目以降を切り捨て → 1333.26 ✓
    *> ただし小数3桁を超える場合は切り捨てになる

    *> 例: 桁が足りないケース
    MOVE 1       TO WS-PRICE
    MOVE .333    TO WS-RATE
    COMPUTE WS-RESULT-A = WS-PRICE * WS-RATE
    *> 1 * 0.333 = 0.333
    *> PIC 9(7)V99(小数2桁)に格納 → 0.33(3桁目を切り捨て)

    *--- ROUNDED指定あり(四捨五入)---
    COMPUTE WS-RESULT-B ROUNDED = WS-PRICE * WS-RATE
    *> 0.333 → 0.33(3桁目は3なので切り捨て、この例では結果が同じ)

    MOVE .666 TO WS-RATE
    COMPUTE WS-RESULT-A = WS-PRICE * WS-RATE
    *> 0.666 → 0.66(切り捨て)
    COMPUTE WS-RESULT-B ROUNDED = WS-PRICE * WS-RATE
    *> 0.666 → 0.67(四捨五入: 3桁目が6 >= 5 なので繰り上げ)

    DISPLAY '切り捨て: ' WS-RESULT-A   *> 0.66
    DISPLAY '四捨五入: ' WS-RESULT-B   *> 0.67
    STOP RUN.
注意: 切り捨てと四捨五入の差が積み重なる
1件あたり数円の差でも、100万件処理すると数百万円の差額になります。金融・会計システムでは丸め方式の選択が法的・業務的に定められている場合があるため、設計段階で丸め方式を明示的に決定し、コードに反映することが重要です。

ROUNDEDの書き方とROUNDING MODE

COMPUTE文やADD・SUBTRACT・MULTIPLY・DIVIDE文でROUNDEDを指定する方法と、COBOL 2002以降で使えるROUNDING MODE(丸めモード指定)を紹介します。

ROUNDEDの基本的な書き方
*> COMPUTE文でROUNDED(デフォルトはHALF-UP = 四捨五入)
COMPUTE 受け取り変数 ROUNDED = 計算式.

*> ROUNDING MODEで丸め方式を明示(COBOL 2002以降)
COMPUTE 受け取り変数 ROUNDED MODE IS HALF-UP       = 計算式.
COMPUTE 受け取り変数 ROUNDED MODE IS HALF-EVEN     = 計算式.
COMPUTE 受け取り変数 ROUNDED MODE IS HALF-DOWN     = 計算式.
COMPUTE 受け取り変数 ROUNDED MODE IS UP            = 計算式.
COMPUTE 受け取り変数 ROUNDED MODE IS DOWN          = 計算式.
COMPUTE 受け取り変数 ROUNDED MODE IS TRUNCATION    = 計算式.

*> 算術文でも同様に使える
ADD  WS-A TO WS-B ROUNDED.
SUBTRACT WS-A FROM WS-B ROUNDED.
MULTIPLY WS-A BY WS-B ROUNDED.
DIVIDE WS-A BY WS-B GIVING WS-C ROUNDED.

6つの丸めモードと業務別の使い分け

COBOLには6種類の丸めモードがあります。どのモードが適切かは業務要件によって異なります。

モード 名称 動作 例(小数2桁) 主な用途
HALF-UP 四捨五入 0.5以上→切り上げ、未満→切り捨て 2.345→2.35 / 2.344→2.34 一般的な計算・日本の税計算(消費税以外)
HALF-EVEN
(銀行家の丸め)
偶数丸め 端数が0.5のとき近い偶数に丸める 2.345→2.34 / 2.355→2.36 銀行・証券・統計処理(偏りを防ぐ)
HALF-DOWN 五捨六入 0.5超え→切り上げ、以下→切り捨て 2.345→2.34 / 2.346→2.35 一部の特殊業務
UP 切り上げ 端数があれば常に切り上げ 2.341→2.35 / -2.341→-2.34 消費税の小数端数(税額に端数がある場合)
DOWN 切り捨て 端数を常に捨てる(0方向へ) 2.349→2.34 / -2.349→-2.34 消費税計算・給与の円未満端数
TRUNCATION 桁で切り捨て DOWNと同じ(ゼロ方向への切り捨て) 2.349→2.34 ROUNDED省略時のデフォルト
HALF-EVENを使う理由(銀行家の丸め)
純粋なHALF-UP(四捨五入)を大量の数値に適用すると、端数0.5のケースが常に切り上げになるため、合計値が実際より高くなる統計的な偏りが生じます。HALF-EVENは0.5のとき偶数側に丸めるため、切り上げと切り捨てが平均的に半々になり、大量データの合計誤差が相殺されます。IEEEの浮動小数点標準やExcelのROUND関数もHALF-EVENを採用しています。
各ROUNDINGモードの動作確認コード
WORKING-STORAGE SECTION.
01 WS-VAL      PIC 9(3)V999 VALUE 1.005.    *> 3桁目に丸める
01 WS-R1       PIC 9(3)V99.
01 WS-R2       PIC 9(3)V99.
01 WS-R3       PIC 9(3)V99.
01 WS-R4       PIC 9(3)V99.
01 WS-R5       PIC 9(3)V99.

PROCEDURE DIVISION.
    COMPUTE WS-R1 ROUNDED MODE IS HALF-UP    = WS-VAL
    COMPUTE WS-R2 ROUNDED MODE IS HALF-EVEN  = WS-VAL
    COMPUTE WS-R3 ROUNDED MODE IS UP         = WS-VAL
    COMPUTE WS-R4 ROUNDED MODE IS DOWN       = WS-VAL
    COMPUTE WS-R5 ROUNDED MODE IS TRUNCATION = WS-VAL

    DISPLAY 'HALF-UP:    ' WS-R1   *> 1.01(5以上→切り上げ)
    DISPLAY 'HALF-EVEN:  ' WS-R2   *> 1.00(偶数の0に近い)
    DISPLAY 'UP:         ' WS-R3   *> 1.01(端数あり→切り上げ)
    DISPLAY 'DOWN:       ' WS-R4   *> 1.00(常に切り捨て)
    DISPLAY 'TRUNCATION: ' WS-R5   *> 1.00(同上)

    *> 1.015の場合
    MOVE 1.015 TO WS-VAL
    COMPUTE WS-R1 ROUNDED MODE IS HALF-UP    = WS-VAL
    COMPUTE WS-R2 ROUNDED MODE IS HALF-EVEN  = WS-VAL
    DISPLAY '--- 1.015 ---'
    DISPLAY 'HALF-UP:    ' WS-R1   *> 1.02(5以上→切り上げ)
    DISPLAY 'HALF-EVEN:  ' WS-R2   *> 1.02(偶数の2に近い)
    STOP RUN.

FUNCTION ROUNDとFUNCTION INTEGER-PART

COBOL 2002以降の組み込み関数でも丸め処理が可能です。COMPUTE + ROUNDEDとの使い分けを解説します。

方法 説明 使いどころ
COMPUTE … ROUNDED 演算結果の小数部を丸めて変数に格納。丸めモードを細かく指定できる 計算結果の格納に直接使える
FUNCTION ROUND(数値, 桁数) 指定した桁数で丸めた値を返す。整数桁への丸め(十の位・百の位など)も可能 任意の桁数で丸めたいとき
FUNCTION INTEGER(数値) 0方向への切り捨てで整数部を返す(DOWN相当) 確実な切り捨て整数変換
FUNCTION INTEGER-PART(数値) INTEGER と同じ(0方向への整数部) INTEGER の別名
FUNCTION ROUNDの使用例
WORKING-STORAGE SECTION.
01 WS-VAL       PIC 9(7)V999.
01 WS-RESULT    PIC 9(7)V99.
01 WS-INT       PIC 9(7).

PROCEDURE DIVISION.
    MOVE 12345.675 TO WS-VAL

    *> 小数2桁に丸める(正の桁数 = 小数点以下桁数)
    MOVE FUNCTION ROUND(WS-VAL, 2) TO WS-RESULT
    DISPLAY '小数2桁丸め: ' WS-RESULT     *> 12345.68

    *> 整数に丸める(桁数=0)
    MOVE FUNCTION ROUND(WS-VAL, 0) TO WS-INT
    DISPLAY '整数丸め: ' WS-INT           *> 12346

    *> 十の位に丸める(負の桁数)
    MOVE FUNCTION ROUND(WS-VAL, -1) TO WS-INT
    DISPLAY '十の位丸め: ' WS-INT         *> 12350

    *> 百の位に丸める
    MOVE FUNCTION ROUND(WS-VAL, -2) TO WS-INT
    DISPLAY '百の位丸め: ' WS-INT         *> 12300

    *> FUNCTION INTEGER(切り捨て)
    MOVE FUNCTION INTEGER(12345.99) TO WS-INT
    DISPLAY '切り捨て: ' WS-INT           *> 12345

    *> 負の数に注意: INTEGERは0方向
    MOVE FUNCTION INTEGER(-12345.3) TO WS-INT
    DISPLAY '負数切り捨て: ' WS-INT       *> -12345(-12346ではない)
    STOP RUN.
FUNCTION ROUNDのモードはHALF-UP固定
FUNCTION ROUNDはHALF-UP(四捨五入)固定です。丸めモードを選択したい場合はCOMPUTE … ROUNDED MODE IS を使いましょう。FUNCTION ROUNDは「任意の桁数で丸める」用途(十の位・百の位への丸めなど)に向いています。

消費税計算の端数処理パターン

日本の消費税計算では端数処理のルールが重要です。国税庁の規定では「消費税額に1円未満の端数が生じた場合、切り捨て・切り上げ・四捨五入のいずれも認められる」とされていますが、実務では切り捨てが最も一般的です。

消費税計算(内税・外税・軽減税率対応)
WORKING-STORAGE SECTION.
*> 商品情報
01 WS-PRICE-NORM     PIC 9(9)V99.   *> 標準税率対象金額(10%)
01 WS-PRICE-REDUCED  PIC 9(9)V99.   *> 軽減税率対象金額(8%)
*> 税率
01 WS-TAX-RATE-NORM  PIC V99        VALUE .10.
01 WS-TAX-RATE-RED   PIC V99        VALUE .08.
*> 計算結果(小数3桁で計算してから切り捨て)
01 WS-TAX-NORM-RAW   PIC 9(9)V999.  *> 計算中間値(小数3桁)
01 WS-TAX-RED-RAW    PIC 9(9)V999.
01 WS-TAX-NORM       PIC 9(9)V99.   *> 切り捨て後(円未満カット)
01 WS-TAX-RED        PIC 9(9)V99.
01 WS-TOTAL          PIC 9(9)V99.

PROCEDURE DIVISION.
    MOVE 10000.00 TO WS-PRICE-NORM
    MOVE  5000.00 TO WS-PRICE-REDUCED

    *--- 切り捨て方式(最も一般的)---
    *> 中間値を小数3桁で計算してからCOMPUTE DOWNで切り捨て
    COMPUTE WS-TAX-NORM-RAW = WS-PRICE-NORM * WS-TAX-RATE-NORM
    COMPUTE WS-TAX-NORM ROUNDED MODE IS DOWN = WS-TAX-NORM-RAW
    *> 10000.00 * 0.10 = 1000.000 → 1000.00(端数なしだが処理は統一)

    COMPUTE WS-TAX-RED-RAW = WS-PRICE-REDUCED * WS-TAX-RATE-RED
    COMPUTE WS-TAX-RED ROUNDED MODE IS DOWN = WS-TAX-RED-RAW
    *> 5000.00 * 0.08 = 400.000 → 400.00

    COMPUTE WS-TOTAL = WS-PRICE-NORM + WS-PRICE-REDUCED
                       + WS-TAX-NORM + WS-TAX-RED
    DISPLAY '標準税率金額: ' WS-PRICE-NORM  *> 10000.00
    DISPLAY '標準税額:     ' WS-TAX-NORM    *> 1000.00
    DISPLAY '軽減税率金額: ' WS-PRICE-REDUCED *> 5000.00
    DISPLAY '軽減税額:     ' WS-TAX-RED     *> 400.00
    DISPLAY '合計(税込): ' WS-TOTAL        *> 16400.00
    STOP RUN.
消費税計算での丸めタイミング

  • 1取引ごとに丸める: 各明細行で税額を計算・丸め。レジ・請求書の明細計算に多い
  • 合計後に丸める: 全明細の税抜合計を求めてから一括で税計算・丸め。誤差が小さい

「1取引ごと」と「合計後」では端数処理タイミングが異なるため、合計額に1〜数円の差が生じることがあります。システム設計時にどちらの方式を採用するか明確にしておきましょう。

給与計算の端数処理パターン

給与計算では日割り・時間給の計算で端数が生じます。労働基準法では「賃金は全額払い」が原則ですが、1円未満の端数は「切り捨て・四捨五入どちらも可」とされています。実務では切り捨てが多く使われます。

日割り給与・時間外賃金の計算
WORKING-STORAGE SECTION.
01 WS-MONTHLY-SALARY  PIC 9(7)V99.    *> 月額給与
01 WS-WORK-DAYS       PIC 9(2).       *> 実際の出勤日数
01 WS-TOTAL-DAYS      PIC 9(2) VALUE 21. *> 月の所定労働日数
01 WS-HOURLY-RATE     PIC 9(6)V9(4).  *> 時間単価(計算中間値)
01 WS-OVERTIME-HOURS  PIC 9(3)V9(2).  *> 時間外労働時間
01 WS-OVERTIME-PAY    PIC 9(7)V99.    *> 時間外賃金
01 WS-DAY-PAY-RAW     PIC 9(9)V9(4).  *> 日割り計算中間値
01 WS-DAY-PAY         PIC 9(7).       *> 日割り給与(円以下切り捨て)

PROCEDURE DIVISION.
    MOVE 300000.00 TO WS-MONTHLY-SALARY
    MOVE 18        TO WS-WORK-DAYS

    *--- 日割り計算(円未満切り捨て)---
    COMPUTE WS-DAY-PAY-RAW = WS-MONTHLY-SALARY
                            / WS-TOTAL-DAYS
                            * WS-WORK-DAYS
    *> 300000 / 21 * 18 = 257142.857...
    COMPUTE WS-DAY-PAY ROUNDED MODE IS DOWN = WS-DAY-PAY-RAW
    *> → 257142円(円未満切り捨て)
    DISPLAY '日割り給与: ' WS-DAY-PAY    *> 257142

    *--- 時間外賃金(割増賃金: 月給÷所定時間×1.25)---
    *> 時間単価 = 月給 / (所定労働日数 * 8時間)
    COMPUTE WS-HOURLY-RATE = WS-MONTHLY-SALARY
                           / (WS-TOTAL-DAYS * 8)
    *> 300000 / 168 = 1785.7142...

    MOVE 10.00 TO WS-OVERTIME-HOURS
    COMPUTE WS-OVERTIME-PAY ROUNDED MODE IS DOWN =
            WS-HOURLY-RATE * WS-OVERTIME-HOURS * 1.25
    *> 1785.71... * 10 * 1.25 = 22321.42... → 22321円
    DISPLAY '時間外賃金: ' WS-OVERTIME-PAY   *> 22321
    STOP RUN.

帳票集計での端数合計不一致と解決策

明細行ごとに丸めた金額を合計すると、合計欄を直接計算した値と一致しないことがあります。この「端数合計不一致」は帳票・請求書でよく発生する問題です。

端数合計不一致が起きる例
WORKING-STORAGE SECTION.
01 WS-ITEM-TABLE.
   05 WS-ITEM OCCURS 3 TIMES.
      10 WS-PRICE   PIC 9(7)V99.
      10 WS-TAX     PIC 9(7)V99.
      10 WS-TOTAL   PIC 9(7)V99.
01 WS-SUBTOTAL   PIC 9(9)V99.
01 WS-TAX-TOTAL  PIC 9(9)V99.
01 WS-GRAND-TOTAL PIC 9(9)V99.
01 WS-CALC-TOTAL  PIC 9(9)V99.
01 WS-TAX-RAW    PIC 9(9)V999.
01 WS-IDX        PIC 9(1).

PROCEDURE DIVISION.
    *> 3行の明細(各行で税額を切り捨て)
    MOVE 333.00 TO WS-PRICE(1)   *> 333.00 * 0.10 = 33.30  → 33.30
    MOVE 333.00 TO WS-PRICE(2)   *> 333.00 * 0.10 = 33.30  → 33.30
    MOVE 334.00 TO WS-PRICE(3)   *> 334.00 * 0.10 = 33.40  → 33.40

    MOVE 0 TO WS-SUBTOTAL WS-TAX-TOTAL

    PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > 3
        COMPUTE WS-TAX-RAW = WS-PRICE(WS-IDX) * .10
        COMPUTE WS-TAX(WS-IDX) ROUNDED MODE IS DOWN = WS-TAX-RAW
        ADD WS-PRICE(WS-IDX) TO WS-SUBTOTAL
        ADD WS-TAX(WS-IDX)   TO WS-TAX-TOTAL
    END-PERFORM

    *> 明細行の税額合計: 33.30 + 33.30 + 33.40 = 100.00
    *> 直接計算:  (333+333+334) * 0.10 = 1000 * 0.10 = 100.00
    *> (今回はたまたま一致しているが、端数次第でずれる)

    *> ずれる例(小数点桁数が多い場合)
    COMPUTE WS-CALC-TOTAL = WS-SUBTOTAL * .10
    COMPUTE WS-GRAND-TOTAL ROUNDED MODE IS DOWN = WS-CALC-TOTAL
    *> 合計後に計算した税額
    DISPLAY '行ごと合計: ' WS-TAX-TOTAL    *> 100.00
    DISPLAY '一括計算:   ' WS-GRAND-TOTAL  *> 100.00
端数不一致の解決策:最終行で調整する方式
*> 解決策: 最初のn-1行を切り捨て計算し、最後の行で差額を調整する
WORKING-STORAGE SECTION.
01 WS-PRICES.
   05 WS-PRC PIC 9(7)V99 OCCURS 5 TIMES.
01 WS-TAXES.
   05 WS-TAX PIC 9(7)V99 OCCURS 5 TIMES.
01 WS-TOTAL-PRICE PIC 9(9)V99.
01 WS-TOTAL-TAX   PIC 9(9)V99.
01 WS-CORRECT-TAX PIC 9(9)V99.    *> 合計額から直接計算した正確な税額
01 WS-ADJUST      PIC S9(7)V99.   *> 最終行の調整額
01 WS-IDX         PIC 9(2).
01 WS-TAX-RAW     PIC 9(9)V999.
01 WS-LAST-IDX    PIC 9(2) VALUE 5.

PROCEDURE DIVISION.
    MOVE 0 TO WS-TOTAL-PRICE WS-TOTAL-TAX

    *> 最初のn-1行: 切り捨てで税額計算
    PERFORM VARYING WS-IDX FROM 1 BY 1
                    UNTIL WS-IDX >= WS-LAST-IDX
        COMPUTE WS-TAX-RAW = WS-PRC(WS-IDX) * .10
        COMPUTE WS-TAX(WS-IDX) ROUNDED MODE IS DOWN = WS-TAX-RAW
        ADD WS-PRC(WS-IDX) TO WS-TOTAL-PRICE
        ADD WS-TAX(WS-IDX) TO WS-TOTAL-TAX
    END-PERFORM

    *> 合計金額から正確な税額を計算(切り捨て)
    ADD WS-PRC(WS-LAST-IDX) TO WS-TOTAL-PRICE
    COMPUTE WS-TAX-RAW = WS-TOTAL-PRICE * .10
    COMPUTE WS-CORRECT-TAX ROUNDED MODE IS DOWN = WS-TAX-RAW

    *> 最終行の税額 = 正確な税額 - それまでの税額合計
    COMPUTE WS-TAX(WS-LAST-IDX) = WS-CORRECT-TAX - WS-TOTAL-TAX
    ADD WS-TAX(WS-LAST-IDX) TO WS-TOTAL-TAX

    *> これで行ごと合計 = 合計後計算の税額が一致する
    DISPLAY '行ごと税額合計: ' WS-TOTAL-TAX
    DISPLAY '一括計算税額:   ' WS-CORRECT-TAX

丸め誤差の累積問題と防止策

ループの中で丸めた値を繰り返し足し込んでいくと、丸め誤差が累積します。利息計算や分割払いの合計額がずれる原因の多くがこれです。

累積誤差が発生するパターンと防止策
WORKING-STORAGE SECTION.
01 WS-PRINCIPAL   PIC 9(9)V99 VALUE 1000000.00.  *> 元本 100万円
01 WS-RATE        PIC V9(5)   VALUE .00137.       *> 日利 0.137%(年利5%相当)
01 WS-INTEREST    PIC 9(7)V99.                    *> 1日の利息(丸め後)
01 WS-BALANCE     PIC 9(12)V99.                   *> 残高(累積)
01 WS-INT-RAW     PIC 9(9)V9(5).                  *> 計算中間値
01 WS-EXACT-TOTAL PIC 9(12)V9(5).                 *> 丸めなしの正確な累積
01 WS-DAYS        PIC 9(3).
01 WS-IDX         PIC 9(3).

PROCEDURE DIVISION.
    MOVE 365 TO WS-DAYS
    MOVE WS-PRINCIPAL TO WS-BALANCE
    MOVE 0 TO WS-EXACT-TOTAL

    *--- NG: 毎日丸めた利息を累積 ---
    PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > WS-DAYS
        COMPUTE WS-INT-RAW = WS-PRINCIPAL * WS-RATE
        COMPUTE WS-INTEREST ROUNDED MODE IS DOWN = WS-INT-RAW
        ADD WS-INTEREST TO WS-BALANCE
    END-PERFORM
    DISPLAY '毎日丸め累積: ' WS-BALANCE

    *--- OK: 丸めなしで累積し、最後に1回だけ丸める ---
    MOVE WS-PRINCIPAL TO WS-EXACT-TOTAL
    COMPUTE WS-EXACT-TOTAL = WS-PRINCIPAL * (1 + WS-RATE * WS-DAYS)
    COMPUTE WS-BALANCE ROUNDED MODE IS DOWN = WS-EXACT-TOTAL
    DISPLAY '一括計算丸め: ' WS-BALANCE
    *> 誤差: 365日で数十円〜数百円の差が生じる場合がある
丸め誤差累積の防止テクニック

  • 中間計算は十分な桁数で保持する: 中間値をPIC 9(n)V9(5)以上で保持し、最終格納時だけ丸める
  • 丸めは最後の1回だけ: 途中で丸めた値を再計算に使うと誤差が積み重なる
  • 合計は元の値から直接計算: 丸め後の値の合計ではなく、丸め前の合計に対して丸めを適用する
  • 差額調整方式: 合計額との差を最終行で調整する(前述の端数合計不一致対策と同じ考え方)

よくある落とし穴と対策

ROUNDEDの指定忘れ 計算結果がデフォルト切り捨てになり、少額の差異が常に生じる。累積すると大きな誤差になる 計算結果を格納するCOMPUTE文には必ずROUNDEDまたはROUNDED MODE IS を明示する
中間計算での桁不足 PIC 9(7)V99 * PIC V99 = 9桁 + 2桁 + 2桁 = 本来11桁必要なのに受け取り変数が小さいと上位桁が失われる 中間計算用変数はPIC 9(12)V9(4)など、十分な桁数を用意する。ON SIZE ERRORで検知する
FUNCTION ROUNDのモード固定 FUNCTION ROUNDはHALF-UP固定。切り捨てしたい場合にFUNCTION ROUNDを使うと誤った結果になる 切り捨て/切り上げなどモードが重要な場合はCOMPUTE ROUNDED MODE IS を使う
負の数の丸め DOWN(切り捨て)は「0方向」への切り捨て。-2.7をDOWNで丸めると-2(-3ではない)。業務要件と合っているか確認が必要 負の数が発生しうる計算では、DOWNとTRUNCATIONの動作を確認して要件に合わせて選択する
合計計算のタイミング 明細行ごとに丸めてから合計すると、合計後に計算した値と一致しないことがある 合計値は丸め前の中間値で加算し、最後に丸めるか、最終行調整方式を採用する

よくある質問

QROUNDED MODE ISはどのCOBOLコンパイラで使えますか?
ACOBOL 2002規格以降の機能です。IBM Enterprise COBOL 6.1以降、GnuCOBOL 2.0以降で対応しています。古いメインフレーム環境(COBOL 85規格以前のコンパイラ)では使用できないため、単純なROUNDEDキーワード(HALF-UP相当)か、手動実装が必要になります。
QROUNDED(モード指定なし)はHALF-UPと同じですか?
Aコンパイラ依存ですが、COBOL標準ではROUNDED(モード指定なし)はHALF-UP(四捨五入)として動作します。IBM Enterprise COBOLでもHALF-UPがデフォルトです。重要な計算では曖昧さを排除するためROUNDED MODE IS HALF-UPと明示する方が安全です。
Q消費税の端数は切り捨て・切り上げ・四捨五入のどれが正しいですか?
A国税庁の規定では3つとも認められており、法的には事業者が自由に選択できます。実務では切り捨てが最も多く使われます。ECサイトや会計システムを開発する際は、会社の方針や既存システムの方式を確認して合わせましょう。軽減税率(8%)と標準税率(10%)を混在させる場合は、税率ごとに税額を計算してから合算するのが一般的です。
Q銀行家の丸め(HALF-EVEN)が必要なのはどんな業務ですか?
A統計的な偏りを防ぎたい大量データ処理に使います。具体的には、銀行の預金利息計算、証券の配当金計算、大量取引の端数集計などです。HALF-UPを使うと端数が0.5のとき常に切り上げになるため、数百万件の計算では合計が常に実際より高くなる偏りが生じます。HALF-EVENは統計学的に偏りがゼロになることが証明されているため、精度が求められる業務で使われます。
QCOMPUTE文以外の算術文でもROUNDEDは使えますか?
Aはい。ADD・SUBTRACT・MULTIPLY・DIVIDEでも受け取り変数の後にROUNDEDを指定できます。ただしROUNDED MODE IS の指定がCOMPUTE文にしか使えないコンパイラもあります。複雑な計算式はCOMPUTE文に統一する方が丸めモードの制御がしやすいです。

まとめ

COBOLの丸め処理は設計段階で方針を決めることが重要です。ポイントを整理します。

用途 方法 説明
デフォルト ROUNDEDなし 切り捨て(TRUNCATION)。意図しない切り捨てに注意
四捨五入 ROUNDED または ROUNDED MODE IS HALF-UP 一般的な計算・日本の税計算(業務依存)
切り捨て ROUNDED MODE IS DOWN 消費税・給与の円未満端数・金融の確実な切り捨て
切り上げ ROUNDED MODE IS UP 端数があれば確実に繰り上げ
偶数丸め ROUNDED MODE IS HALF-EVEN 銀行・証券・大量データの統計的偏り防止
任意桁の丸め FUNCTION ROUND(値, 桁数) 十の位・百の位など整数桁への丸め(HALF-UP固定)
切り捨て整数化 FUNCTION INTEGER(値) 0方向への切り捨て整数変換

丸め処理は「単純に四捨五入すればよい」というものではありません。業務要件・法規制・合計計算のタイミングを整理して、適切な丸め方式を選択しましょう。

COMPUTEの演算子や算術文全般についてはCOMPUTEで計算を行う完全ガイドを、数値操作と合わせてよく使うMOVE文の型変換についてはMOVE文の完全ガイドも参照してください。