現場で生き残るPL/I:FIXED DECIMALとパック10進数の「深淵」を極める
メインフレームの現場で長年バッチ改修を繰り返していると、ふと遭遇するのが「計算精度」という怪物だ。特に金融系や勘定系システムでは、浮動小数点数(FLOAT)の誤差は許されない。そこで我々が頼りにするのは`FIXED DECIMAL`、すなわちパック10進数である。
今回は、PL/Iにおけるこのデータ型の真実と、実務で絶対にハマってはいけない罠について、少し熱く語らせてもらおうと思う。
1. なぜ「パック10進数」が選ばれるのか
まず基本の確認だ。IBMメインフレームの世界において、`FIXED DECIMAL(p, q)`は、内部的には`PACKED-DECIMAL`形式で格納される。これは1バイトに2桁の数値を詰め込み、最後の4ビットで符号(Positive/Negative)を表現する形式だ。
なぜこれを使うのか? それは「10進数としての正確さ」を維持するためだ。バイナリ(2進数)での演算では、0.1のような簡単な数値すら循環小数となり、誤差の蓄積が避けられない。しかし、`FIXED DECIMAL`なら、人間が計算するのと全く同じ論理で正確に計算できる。これが基幹業務で選ばれる唯一無二の理由だ。
2. 実践的なコーディング標準
まずは、典型的な構造のプログラム例を見てほしい。`OPTIONS(MAIN)`での宣言や、演算時の精度維持を意識したコーディングだ。
1
/ —————————————————————— /
/ プログラム名:CALC_SAMPLE /
/ 目的:FIXED DECIMALを使用した正確な演算の実践 /
/ —————————————————————— /
CALC_SAMPLE: PROCEDURE OPTIONS(MAIN);
/ 精度(p)と位取り(q)を明示する。特に計算結果の受け皿には注意 /
DCL W_PRICE FIXED DEC(9, 2) INIT(0);
DCL W_TAX_RATE FIXED DEC(3, 3) INIT(0.08); / 0.080と解釈される /
DCL W_TAX_AMT FIXED DEC(9, 2) INIT(0);
/ VSAMファイル等からの読み込みを想定 /
GET LIST(W_PRICE);
/ 計算処理:演算時の精度劣化を防ぐ /
/ PL/Iは演算過程で自動的に精度を拡大するが、代入時に注意が必要 /
W_TAX_AMT = W_PRICE W_TAX_RATE;
PUT SKIP LIST(‘税込金額:’, W_TAX_AMT);
/ 異常系処理の定石:ONユニットでオーバーフローを検知する /
ON FIXEDOVERFLOW
BEGIN;
PUT SKIP LIST(‘警告:演算結果が桁あふれしました’);
/ ここでログ出力や異常終了処理を呼び出す /
END;
END CALC_SAMPLE;
3. 「計算誤差」と「桁落ち」を防ぐエンジニアの心得
現場でよくある失敗は、「演算結果がどこで切り捨てられるか」を意識していないことだ。
演算中間値の精度ルール
PL/Iのコンパイラは、演算のたびに最適な精度を計算するが、代入先の変数の精度が低いと、そこであっさりと切り捨て(Truncation)が発生する。特に`FIXED DEC(p, q)`同士の掛け算では、精度が`p1+p2`にまで拡大される可能性があることを忘れてはならない。
BUILTIN関数の活用
計算結果を丸めたい場合、むやみに代入するのではなく`ROUND`関数を活用するのが玄人の流儀だ。
1
/ 演算結果を小数点第2位で四捨五入する例 /
W_TAX_AMT = ROUND(W_PRICE W_TAX_RATE, 2);
ONユニットによる防御壁
バッチプログラムで最も恐ろしいのは、計算エラーで異常終了することではなく、「間違った値で正常終了すること」だ。`ON FIXEDOVERFLOW`や`ON SIZE`などの条件処理(ON-Unit)を適切に定義し、計算精度が保てなくなった瞬間に検知できる体制を構築しておくこと。これが、保守担当者としての最後の防波堤となる。
4. 最後に:メインフレームエンジニアへのアドバイス
「古い言語だから」と言ってPL/Iを侮ってはいけない。現代のJavaやPythonであっても、金融系の基幹ロジックでは結局「固定小数点」の概念を再実装しているに過ぎないのだから。
VSAMのレコードレイアウト定義(COPYBOOK)と、プログラム内の`DCL`が一致しているか、常に神経を尖らせてほしい。`PIC`句の使い方一つで、データの表現力は全く変わる。
もし、バッチ処理で不可解な誤差が発生したときは、コンパイラリストの「Attributes」セクションを眺めてみよう。君が宣言した変数が、コンパイラによってどう解釈され、どのような中間精度で演算されているか、すべてそこに記されているはずだ。
泥臭いデバッグこそが、最強のスキルになる。健闘を祈る。
