【COBOL学習|実務向け】[実務でハマる罠:COMP-1/2(浮動小数点)転記の誤差と正しい向き合い方]

1. 導入:なぜ浮動小数点の扱いに注意が必要なのか

COBOL開発の現場において、金額計算にCOMP-3(パック十進数)を使うのは常識ですが、稀に科学技術計算や統計処理でCOMP-1(単精度浮動小数点)やCOMP-2(倍精度浮動小数点)に触れることがあります。ここで最も重要なのは「浮動小数点は、私たちが普段目にする十進数の値を、内部的に正確に表現できないことがある」という点です。この特性を理解せずにMOVE命令を使うと、計算結果に微小な誤差が紛れ込み、後続の条件判定(IF文など)で予期せぬ不具合を引き起こす原因となります。

2. 基礎知識:浮動小数点の仕組み

浮動小数点は、数値を「仮数部」と「指数部」に分けて保持するデータ形式です。コンピュータ内部では二進数として扱われるため、0.1のような「十進数で有限の小数」であっても、二進数に変換すると「循環小数」となり、桁あふれした分が切り捨てられます。

  • COMP-1:単精度(4バイト)。精度は約7桁。
  • COMP-2:倍精度(8バイト)。精度は約15〜17桁。

これらは非常に大きな値や極めて小さな値を扱うのには適していますが、1円単位の正確さが求められる業務アプリケーションの「金額」を扱う用途には全く適していません。

3. 実装・解決策:安全なデータ操作の鉄則

浮動小数点項目を扱う際の鉄則は「比較には絶対値を用いる」こと、そして「なるべく固定小数点数(DISPLAYやCOMP-3)へ変換してから判定する」ことです。特に、浮動小数点同士の等値比較(IF A = B)は、微小な誤差により期待通りに動作しない可能性が高いため、避けるべきです。

4. サンプルプログラム:誤差を確認するコード

以下のコードは、浮動小数点の誤差を確認し、それを回避するための比較ロジック例です。

IDENTIFICATION DIVISION.
PROGRAM-ID. FLOAT-TEST.

DATA DIVISION.
WORKING-STORAGE SECTION.

  • 浮動小数点項目の定義

01 WS-FLOAT-COMP1 COMP-1.
01 WS-CHECK-VALUE COMP-1 VALUE 0.1.

  • 比較用(固定小数点)

01 WS-FIXED-DECIMAL PIC S9(5)V9(2).

PROCEDURE DIVISION.

  • 0.1を転記(内部的には厳密に0.1ではない場合がある)

MOVE 0.1 TO WS-FLOAT-COMP1.

  • 【注意】直接比較は危険な場合がある

IF WS-FLOAT-COMP1 = 0.1 THEN
DISPLAY “一致しました”
ELSE
DISPLAY “誤差により不一致”
END-IF.

  • 【解決策】許容誤差(イプシロン)を設けた判定
  • 差分が非常に小さい(0.000001以下)なら一致とみなす手法

COMPUTE WS-FLOAT-COMP1 = WS-FLOAT-COMP1 – 0.1.
IF FUNCTION ABS(WS-FLOAT-COMP1) < 0.000001 THEN DISPLAY "許容範囲内で一致とみなします" END-IF. STOP RUN.

5. 応用・注意点:現場での回避策

現場で浮動小数点を利用せざるを得ない場合、以下の点に注意してください。

金額計算には絶対に使用しない:金額計算には必ずCOMP-3(パック十進数)を使用してください。
等値比較を避ける:浮動小数点同士の「=」比較は原則禁止です。引き算を行い、その絶対値が十分に小さい値(イプシロン)以下であるかどうかで判定してください。
データの型変換に注意:COMP-1/2からCOMP-3へMOVEする際は、端数処理が発生します。どのタイミングで丸めが行われるかを仕様書で明確に定義し、テストケースで境界値を必ず確認することが重要です。

浮動小数点は「便利だが気難しいツール」です。その特性を正しく理解し、安全な実装を心がけましょう。

コメント

タイトルとURLをコピーしました