PL/Iの「PRECISION」でハマるな:動的精度変更が引き起こす隠れたコストと罠
現場の諸君、今日もメインフレームの迷宮で格闘していることと思う。
大規模改修やマイグレーションの現場で、既存の計算ロジックに手を加える際、もっとも「触りたくない」が「避けて通れない」のが数値の精度(PRECISION)問題だ。
特に、`PRECISION`ビルトイン関数を安易に使って「なんとなく計算が合わないから」と桁数をいじっている諸君、その背後でコンパイラが何をしているか、想像したことはあるか?今回は、この精度の変更がシステムに与えるインパクトと、正しい向き合い方について、ベテランの視点から説いていく。
—
1. PRECISIONビルトイン関数の正体
PL/Iにおける `PRECISION(x, p, q)` は、単なる型のキャストではない。これは、コンパイラに対して「この変数のビット表現を再構成せよ」と命じる強力な命令だ。
- x: 対象となる数値変数
- p: 新しい精度(全体の桁数)
- q: 新しいスケール(小数部桁数)
この関数が呼ばれると、コンパイラは実行時に変換ルーチンを呼び出すための追加コードを生成する。つまり、単なる代入と比較して、CPUサイクルを確実に消費する。数万件のレコードを処理するバッチなら誤差だが、数億件のVSAMアクセスを伴う突き合わせ処理のループ内でこれを叩けば、オンラインレスポンスやバッチの終了時間に如実に跳ね返ってくるのだ。
—
2. 実践コード:VSAM読み込み時の精度変換
例えば、外部システムから受け取った古いVSAMファイル(`FIXED BINARY(15)`)を、現行の計算ロジック(`FIXED DECIMAL(15, 2)`)に合わせる際、現場でよく見かけるコードを見てみよう。
1
PACKAGE_MAIN: PACKAGE;
/ メイン処理:バッチの入り口 /
PROCESS_DATA: PROCEDURE OPTIONS(MAIN);
DCL IN_RECORD_VAL FIXED BIN(15); / VSAMから読み込んだ生の値 /
DCL CALC_VAL FIXED DEC(15, 2); / 計算用の高精度変数 /
/ 読み込み処理(簡略化) /
READ FILE(IN_VSAM) INTO(REC_BUFFER);
/ 【重要】PRECISIONによる変換の例 /
/ 内部的には一時的なワーク領域が確保され、変換処理が走る /
CALC_VAL = PRECISION(IN_RECORD_VAL, 15, 2);
/ ここでONユニットによる例外制御を挟むのが堅牢な設計だ /
ON CONVERSION BEGIN;
PUT SKIP LIST(‘データ変換エラー発生:不正な数値です’);
/ 適切なエラーハンドリングを行い、異常終了を回避する /
SIGNAL CONDITION(ERR_CONDITION);
END;
END PROCESS_DATA;
END PACKAGE_MAIN;
—
3. ベテランが教える「避けるべき実装」と「最適化のコツ」
罠その1:ループ内での多用
`PRECISION`をループ内で直接書くのは、パフォーマンスチューニングの観点からは悪手だ。もし同じ精度変換を繰り返すのであれば、一度型を定義した変数に代入してから計算するほうが、コンパイラにとっても最適化の余地が生まれる。
罠その2:固定小数点への無自覚な変換
`FIXED BINARY`と`FIXED DECIMAL`を混ぜると、PL/Iは暗黙の型変換(コンバージョン)を行う。ここに`PRECISION`を重ねると、コンパイラは「どの桁で丸めるか」の論理を組み込むため、予期せぬ桁落ち(Truncation)が発生するリスクがある。計算結果が仕様書と一致しない場合、この「変換タイミング」がズレていないかを確認するのがデバッグの定石だ。
罠その3:ONユニットの過信
`PRECISION`で無理やり変換しようとして、`FIXEDOVERFLOW`や`CONVERSION`の例外を発生させ、それを`ON`ユニットで拾う設計はあまり推奨しない。オーバーヘッドが非常に大きく、バッチの実行効率を著しく下げるからだ。可能な限り、変換前に値の範囲チェック(`IF`文による事前バリデーション)を行うのが、真のプロのコーディングだ。
—
最後に:諸君に伝えたいこと
PL/Iは、ハードウェアの能力を極限まで引き出せる言語だ。しかし、それは「コンパイラが裏で何を考え、CPUがどの命令を実行しているか」を理解しているエンジニアに対してのみ、その恩恵を授ける。
「動けばいい」というコードは、メンテナンス担当者にとっての地雷でしかない。精度を変更するときは、必ずその変換コストと、例外発生時の制御フローをセットで設計すること。これが、大規模なメインフレーム基幹システムを長期間守り抜くための唯一の道である。
次回は、`STRUCTURE`の配置と`ALIGNED`/`UNALIGNED`属性によるメモリ効率について深掘りしようと思う。現場からは以上だ。質問があればいつでも聞いてくれ。
