こんにちは。メインフレームの世界へようこそ。
JavaやCOBOLというモダンで便利な環境から、突如として「PL/I」という歴史ある言語の前に立たされたあなたの不安、痛いほどわかります。
「なぜ今さらPL/Iなのか?」「この不思議なデータ型は何なんだ?」と頭を抱えているあなたへ。今日は、基幹システムの心臓部である「パック10進数(FIXED DECIMAL)」について、その正体と付き合い方を紐解いていきましょう。
—
1. なぜ「パック10進数」が必要なのか?
Javaで `double` や `float` を使って金額計算をしたことはありますか? もしあれば、「0.1 + 0.2 が 0.30000000000000004 になる」という誤差の洗礼を受けたことがあるはずです。
基幹システム、特にお金の計算では、この「1円のズレ」が許されません。そこで登場するのが、FIXED DECIMAL(p,q) です。これは「10進数として正確に数値を保持する」ための仕組みで、メインフレーム界隈では「COMP-3(コンプ・スリー)」と呼ばれます。
イメージしてみましょう
例えば、`FIXED DECIMAL(5,2)` と宣言した場合、これは「全体で5桁、そのうち小数点以下が2桁」という意味になります。
メモリ上では、数字の「1」を1バイト使わず、「半バイト(4ビット)に1桁の数字を詰め込む」という、極めてストイックな省スペース化を行っています。最後の半バイトは符号(プラスかマイナスか)のために使われる……これがパック10進数の「詰め込み技術」の正体です。
—
2. PL/Iでの宣言と実務のコード例
では、実際にPL/Iでどのように書くのか見てみましょう。基本構造である `PACKAGE` や `PROCEDURE` とセットで確認します。
1
/ メインプログラムの基本構造 /
MY_CALC: PROCEDURE OPTIONS(MAIN);
/ 宣言:5桁(うち小数2桁)のパック10進数 /
/ イメージ:123.45 といった数値が正確に格納されます /
DCL AMOUNT FIXED DECIMAL(5,2) INIT(0);
/ 計算用の変数 /
DCL TAX_RATE FIXED DECIMAL(3,2) INIT(1.08);
/ 演算:PL/Iは柔軟ですが、型には厳しい一面もあります /
AMOUNT = 100.00;
AMOUNT = AMOUNT TAX_RATE;
/ 処理の終了 /
RETURN;
END MY_CALC;
見ての通り、COBOLの `PIC S9(3)V99 COMP-3` とほぼ同じ感覚で扱えますよね。PL/Iはこれに加えて、計算の過程で小数点位置がずれたとしても、コンパイラが自動的にアライメント(位置合わせ)を調整してくれるという、非常に賢い側面を持っています。
—
3. なぜ「変換コスト」を気にする必要があるのか?
ここからがアーキテクトとしての現場の知恵です。
PL/Iが自動で型変換(例:`FIXED DECIMAL` と `BINARY FLOAT` の混在演算)を行ってくれるのは便利なのですが、この裏側では、CPUがせっせと「パック10進数から浮動小数点形式への変換」を行っています。
- 頻繁な型変換はバッチの敵:
数百万件のレコードを処理するバッチプログラムで、ループの中で毎回わざわざデータ型を変換するようなコードを書くと、処理時間は目に見えて悪化します。「型を合わせる」という意識を持つだけで、メインフレームのCPUパワーを無駄に消費させずに済みます。
- アライメントの罠:
`FIXED DECIMAL(p,q)` を宣言する際、p(精度)を必要以上に大きく取らないのがコツです。無駄に大きな精度を確保すると、計算負荷が上がります。「必要な分だけ確保する」……このシンプルかつ職人肌な設計が、メインフレームの性能を最大限に引き出します。
—
最後に:怖がる必要はありません
PL/Iのコードは、最初は確かに「大文字ばかりで無機質」に見えるかもしれません。しかし、これは「データに対して非常に誠実な言語」でもあります。
- データの桁数が溢れれば、即座に例外(ON条件)として通知してくれる。
- 計算誤差を極限まで排除する設計になっている。
これらは、基幹システムを30年、40年と止めずに動かし続けてきた先人たちの知恵そのものです。
もしコードを読んでいて「なぜここでこの宣言なのか?」と迷ったら、それは「そのデータが、システムにとってどれだけ重要か」を先人が示してくれている証拠です。一つずつ紐解けば、必ず道は見えます。
また何か詰まったら、いつでも聞きに来てくださいね。一緒にコードの海を泳いでいきましょう。
