なぜ今さら『PIC ‘V’』なのか?――メインフレーム・アーキテクトが語る、数値精度の「落とし穴」
若手の諸君、日々のバッチ改修お疲れ様。
最近はJavaやPythonといったモダン言語での開発が主流になりつつあるが、我々が守っている基幹システムの心臓部には、依然としてPL/Iが脈々と流れている。特に、金融や物流の勘定系バッチにおいて、「なぜか計算結果が合わない」「端数処理で誤差が出る」というトラブルは、いまだに絶えない。
その原因の9割は、PICTURE句における仮想小数点(’V’)の理解不足にある。今日は、仕様書を眺めるだけでは分からない、現場で生き残るための「V」の取り扱いについて、少し深い話をしよう。
—
1. PIC ‘V’ は「小数点」ではない。それは「境界」である
まず、大前提を叩き込んでおいてほしい。`PIC ’99V99’` と書いたとき、そこには実際のドット(.)は存在しない。これは、「内部表現としては整数として扱いつつ、論理的な小数点の位置をコンパイラに教える」という、極めてメインフレームらしい効率的な仕組みだ。
例えば、`1234` というデータがあるとする。
- `PIC ’99V99’` ならば、内部的には `12.34` として扱われる。
- `PIC ‘9999V’` ならば、内部的には `1234.` (整数)として扱われる。
この「V」の位置がずれるとどうなるか? 演算時の自動位置合わせ(アライメント)が狂い、数値が10倍になったり100倍になったりする。マイグレーションの際、他言語への変換で最もバグを産みやすいのがこの「仮想」という概念の取り扱いだ。
—
2. 実践コード:演算とデータ制御の黄金パターン
では、実際のバッチ処理でよくある、VSAMファイルから読み込んだ数値を加工して出力するパターンのコードを見てみよう。PL/Iのコンパイラは、異なる`PIC`定義同士の演算でも、自動的に「V」の位置を合わせて演算を行ってくれる。これがPL/Iの強力な点であり、同時に注意が必要な点でもある。
1
/ ————————————————————– /
/ サンプルプログラム:売上計算バッチの一部 /
/ ————————————————————– /
TEST_CALC: PROCEDURE OPTIONS(MAIN);
/ 入力データ定義:税抜き金額(整数部4桁、小数部2桁) /
DCL IN_AMT_TAX_EX PIC ‘9999V99’;
/ 演算用変数:計算結果(税率を考慮するため小数部を多めに確保) /
DCL WK_TAX_RESULT FIXED DEC(11, 4);
/ 出力データ定義:税込み金額(編集記号付き) /
DCL OUT_AMT_TAX_IN PIC ‘ZZZZ9.99’;
/ 擬似的な読み込み処理 /
IN_AMT_TAX_EX = 100025; / 1000.25として扱われる /
/ 演算処理:消費税8%を掛ける /
/ PL/Iは演算時にVの位置を自動で揃えるため、意識的に精度を保つ /
WK_TAX_RESULT = IN_AMT_TAX_EX 1.08;
/ 編集出力:小数点位置を確定させて文字列化 /
OUT_AMT_TAX_IN = WK_TAX_RESULT;
PUT SKIP EDIT (‘税込金額:’, OUT_AMT_TAX_IN) (A, A);
END TEST_CALC;
—
3. トラブルシューティング:ONユニットと「V」の相性
現場でよく見る悲劇は、`FIXEDOVERFLOW`(固定小数点オーバーフロー)だ。
計算結果が定義した`PIC`の桁数を超えたとき、PL/Iは標準で割り込みを発生させる。ここで`ON FIXEDOVERFLOW`を適切に制御していないと、ジョブは異常終了(ABEND)する。
特に、`V`を含んだ計算で桁落ちが発生する場合、`ROUND`関数や`TRUNC`関数を正しく使い分けなければならない。私が若手に必ず教えるのは、「計算の受け皿は、常に演算対象よりも大きな精度を持つこと」だ。
1
ON FIXEDOVERFLOW BEGIN;
PUT SKIP LIST (‘エラー:演算結果が桁あふれしました’);
/ 必要に応じてログを出力し、補正処理へ移行する /
END;
—
4. ベテランからのアドバイス:保守の現場で生き抜くために
1. データ変換時は必ず確認せよ: レガシーシステムとオープン系システムの間でデータをやり取りする場合、`PIC ‘V’` はただの数値の羅列(EBCDICやASCIIの文字コード)として扱われることが多い。「V」の意味が消滅しないよう、インターフェース設計時には必ず小数点位置を双方で合意すること。
2. `BUILTIN`関数を恐れるな: `FIXEDDEC`、`DECIMAL`、`ROUND`などのビルトイン関数を使いこなせ。これらはコンパイラが最も効率の良い機械語を生成するように最適化されている。変に自前で計算ロジックを書くより、よほど信頼性が高い。
3. 大文字記述の美学: 古臭いと感じるかもしれないが、大文字の記述には「誰が読んでも同じように解釈できる」という強力な保守性がある。インデントを揃え、コメントで「このVが何を意味しているのか」を明記しておくこと。それが、数年後の君自身の首を救うことになる。
PL/Iは、突き詰めれば非常に論理的で美しい言語だ。`PIC ‘V’` を単なる「記号」としてではなく、「数値の真理を表す設計図」として捉えられるようになったとき、君は本当の意味でメインフレームエンジニアの仲間入りをしたと言えるだろう。
次回のバッチ改修では、ぜひこの「V」の裏側を意識してコードを書いてみてほしい。何かあれば、いつでも相談に乗るぞ。
