【入門編】FLOAT BINARY/DECIMALのIEEE 754準拠と精度 – PL/Iの基本構文とデータ制御実践ガイド

浮動小数点数の「罠」を越えて——PL/Iで扱う数値と精度の深淵

こんにちは。メインフレームの世界へようこそ。
普段、Javaで `double` を使い、COBOLで `COMP-3` を扱っている方々からすると、PL/Iの数値型は少しばかり「クセが強い」と感じるかもしれません。

今回は、基幹システムのマイグレーション現場でエンジニアを最も悩ませるトピックの一つ、「浮動小数点数(FLOAT)」の精度と丸め誤差について紐解いていきます。「計算結果がわずかにズレる……」そんな恐怖に立ち向かうための心得を、一緒に学んでいきましょう。

1. PL/Iの浮動小数点:BINARYかDECIMALか

PL/Iには大きく分けて二つの浮動小数点型があります。

  • FLOAT BINARY: 2進浮動小数点(IEEE 754準拠)。計算速度が爆速。
  • FLOAT DECIMAL: 10進浮動小数点。人間が直感的に計算できる(10進数に近い)。

Javaの `float` や `double` は「2進」ですが、PL/Iでは「どちらを使うか」を意図的に選ぶ必要があります。ここで重要なのは、「コンピュータは2進数で考えている」という事実です。

なぜ誤差が起きるのか?

例えば `0.1` という数字。これを2進数で表現しようとすると、`0.0001100110011…` と無限ループになります。コンピュータのメモリ(ビット)は有限ですから、どこかで切り捨て(丸め)が発生します。これが、バッチ処理の合計金額が1円合わない……なんていう悲劇の元凶なのです。

2. 実際にコードで見てみよう

PL/Iの基本的な構造(`PROCEDURE OPTIONS(MAIN)`)の中で、この誤差がどう現れるか確認してみましょう。

/i
TEST_FLOAT: PROCEDURE OPTIONS(MAIN);

/ FLOAT BINARY(21)は、おおよそ7桁の精度を持つ単精度浮動小数点数です /
DCL VALUE_A FLOAT BINARY(21) INIT(0.1);
DCL VALUE_B FLOAT BINARY(21) INIT(0.3);
DCL RESULT FLOAT BINARY(21);

/ 0.1 + 0.2 は果たして 0.3 になるでしょうか? /
RESULT = 0.1 + 0.2;

IF RESULT = 0.3 THEN
PUT SKIP LIST(‘成功!一致しました’);
ELSE
PUT SKIP LIST(‘失敗!誤差が発生しました:’, RESULT);
/ ここでは 0.30000001 などの値が表示されることが多いです /

END TEST_FLOAT;

見ての通り、コンピュータは「0.1と0.2を足したから0.3だよね」とは考えません。「ビットの並び」で計算するため、わずかなゴミが残るのです。

3. 実務で「誤差」を避けるための鉄則

メインフレームの基幹業務、特に金融・会計システムで「浮動小数点」をそのまま使うのは実は御法度です。以下のポイントを覚えておいてください。

① 「比較」にはイプシロン(許容誤差)を使う

浮動小数点数同士を `IF A = B` で比較するのは厳禁です。「差分が非常に小さい値(例えば 0.000001)」以下なら「等しい」とみなす、という書き方がプロの流儀です。

/i
/ 差の絶対値が十分に小さければ等しいとみなす /
IF ABS(RESULT – 0.3) < 1E-6 THEN PUT SKIP LIST('実質的に一致しました');

② 金額計算には「FIXED DECIMAL」を使う

これが一番の解決策です。PL/Iには `FIXED DECIMAL(15, 2)` のような、「固定小数点数」という型があります。これはCOBOLの `PIC S9(13)V99` と同じ考え方で、誤差が発生しません。金額を扱う時は、迷わずこれを選んでください。

まとめ:怖がる必要はありません

PL/Iの浮動小数点数は、一見すると不親切で「なぜこんなズレるんだ!」と怒りたくなるかもしれません。しかし、これはコンピュータが電気信号を高速に処理するための「最適化の結果」に過ぎないのです。

  • 科学計算や統計 → 速度重視で `FLOAT BINARY`
  • お金や在庫 → 精度重視で `FIXED DECIMAL`

この二つを使い分けるだけで、あなたの書くPL/Iプログラムは圧倒的に堅牢なものになります。

もし、レガシーコードを読んでいて「なぜここで `FLOAT` を使っているんだ?」と疑問に思ったら、それは当時のシステムアーキテクトが「速度」を優先した証拠です。その意図を汲みつつ、現在の要件に合わせて型を再考する。それこそが、メインフレーム・アーキテクトへの第一歩ですよ。

また次回、さらにディープなPL/Iの世界でお会いしましょう!

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