導入: なぜ計算順序で結果が変わるのか?
ベテランの現場では「計算したはずの数値が、ほんのわずかだけ期待値とずれている」という不可解なバグに遭遇することがあります。これはCOBOLのコンパイラが計算途中に保持する「中間結果」の精度が、計算式やデータ定義に依存して変化することが原因です。正確な会計計算や統計処理を行う際、この仕組みを理解していないと、端数処理の段階で致命的な誤差を生む可能性があります。本稿では、安定した演算を行うための作法を解説します。
基礎知識: 中間結果とは何か
COBOLのCOMPUTE文や算術演算では、括弧内の計算や乗除算を行う際、コンパイラは一時的な作業領域(中間結果)を使用します。規格上、この桁数は実装依存ですが、一般的には「演算項の中で最も大きな桁数」に合わせて拡張されます。しかし、あまりに複雑な式を一度に記述すると、コンパイラが内部で桁あふれを防ぐために勝手に精度を調整し、予期せぬ桁落ちが発生することがあります。これを防ぐのが、データ定義と式を分割する「作法」です。
実装/解決策: 精度を制御するコーディング
最も確実な解決策は、「一度の式で全てを終わらせない」ことです。特に除算を含む計算では、先に除算を行って結果を保持するのではなく、乗算を先に行うことで桁落ちを防ぐことが鉄則です。また、計算途中の変数は、常に最終結果よりも大きな桁数を持つように定義しておくことで、中間結果の精度をコンパイラに最大限確保させることができます。
サンプルプログラム: 精度を守る計算例
下記は、割り算の結果を保持する際に精度が落ちるのを防ぎ、かつ可読性を高めたコード例です。
IDENTIFICATION DIVISION.
PROGRAM-ID. CALC-PRECISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
- 最終結果は小数点以下2桁だが、中間変数は4桁で定義して精度を保つ
01 WS-RESULT PIC S9(7)V99.
01 WS-TEMP-CALC PIC S9(7)V9999.
01 WS-VAL-A PIC 9(5) VALUE 100.
01 WS-VAL-B PIC 9(5) VALUE 3.
01 WS-VAL-C PIC 9(5) VALUE 50.
PROCEDURE DIVISION.
- 悪い例: COMPUTE WS-RESULT = (WS-VAL-A / WS-VAL-B) WS-VAL-C
- 割り算が先に行われると、途中で端数が切り捨てられるリスクがある。
- 良い例: 乗算を先に行うことで精度を維持する
COMPUTE WS-TEMP-CALC = (WS-VAL-A WS-VAL-C) / WS-VAL-B.
- 最後に目的の桁数へ丸める
MOVE WS-TEMP-CALC TO WS-RESULT.
DISPLAY “計算結果: ” WS-RESULT.
GOBACK.
応用・注意点: 現場で陥りやすいバグ
現場で最も注意すべきは、「COMPUTE文の長さ」と「PICTURE句の桁数」のバランスです。特に、中間結果がコンパイラの制限(例えば30桁や31桁など)を超えると、コンパイルエラーや実行時の異常終了が発生します。また、ROUNDED句を使用する際は、式全体に適用されるのか、途中の演算に適用されるのかを意識してください。複雑な計算が必要な場合は、面倒でも変数に細かく分解することが、後進のエンジニアにとっても、そして何よりシステム全体の信頼性にとっても最善の選択となります。計算式は「短く書くこと」ではなく「正しく書くこと」を優先しましょう。

コメント