皆さん、こんにちは。基幹システムの現場で長年メインフレームと格闘してきた、PL/Iアーキテクトです。
「PL/I? なんだか古めかしいし、JavaやCOBOLとは少し毛色が違うな……」と身構えていませんか? 大丈夫です。PL/Iは、C言語の柔軟性とCOBOLのデータ処理能力を良いとこ取りしたような、実は非常に理にかなった言語なんですよ。
今回は、PL/Iにおける「数値の箱」のサイズである `FIXED BINARY` と、その境界線で起こるトラブルについて、現場の知見を交えて優しく紐解いていきましょう。
—
1. 予約語がない? PL/Iの自由すぎる識別子
まず最初に驚かれるのが、「PL/Iには明確な予約語がない(あるいは少ない)」という仕様です。
JavaやC言語では `IF` や `WHILE` という名前を自分の変数名に使うことはできませんよね。でもPL/Iは違います。例えば、`IF` という名前の変数を作ることも、文法上は許されてしまいます。
「えっ、それって混乱しないの?」と思いますよね。確かに混乱します(笑)。でも、コンパイラはコンテキスト(文脈)を見て、「これは演算子としてのIFか、それとも変数名のIFか」を判断します。とはいえ、これをやると可読性が最悪になるので、現場では「予約語っぽく見える名前は避ける」というコーディング規約で縛るのが鉄則です。
—
2. FIXED BINARY(15) と (31) :メモリの箱を理解する
さて、ここからが本題です。PL/Iで数値を扱うとき、`FIXED BINARY`(二進固定小数点数)は非常に効率的で、メインフレームのCPU(z/Architecture)が最も得意とする形式です。
内部表現のイメージ
`FIXED BINARY(p)` の `p` は精度(ビット数)を表します。
- FIXED BINARY(15):これは「2バイト(16ビット)」の領域を使います。
- 15ビット+符号1ビット=16ビット。
- 扱える値は -32,768 ~ 32,767 です。C言語の `short` 型に近いですね。
- FIXED BINARY(31):これは「4バイト(32ビット)」の領域を使います。
- 31ビット+符号1ビット=32ビット。
- 扱える値は -2,147,483,648 ~ 2,147,483,647 です。C言語の `int` 型に相当します。
現場で一番多いトラブルは、「計算結果がこの箱に入りきらなくなること」です。
—
3. オーバーフローと「ON FIXEDOVERFLOW」の魔法
もし、`FIXED BINARY(15)` で宣言した変数に、計算結果が32,767を超えてしまったらどうなるでしょうか?
PL/Iは、ここで「見て見ぬふり」をせず、明確なエラー通知を飛ばす仕組みを持っています。それが `ON FIXEDOVERFLOW` です。
現場の実装例
以下のようなコードで、オーバーフローを安全にキャッチできます。
1
/ FIXED BINARY(15)のオーバーフロー検知サンプル /
PROCEDURE OPTIONS(MAIN);
DCL VAL1 FIXED BIN(15) INIT(30000);
DCL VAL2 FIXED BIN(15) INIT(5000);
DCL RESULT FIXED BIN(15);
/ オーバーフロー発生時の処理を定義 /
ON FIXEDOVERFLOW BEGIN;
PUT SKIP LIST(‘警告:値が許容範囲を超えました!’);
/ ここでログ出力や異常終了処理を呼び出すのが現場の作法 /
END;
/ 30000 + 5000 = 35000となり、32767を超えてしまう /
RESULT = VAL1 + VAL2;
PUT SKIP LIST(‘結果は:’ || RESULT);
END;
このように `ON` ユニットを定義しておくと、プログラムが即座に異常終了(ABEND)するのを防ぎ、適切なリカバリ処理を実行できるんです。
—
4. なぜ「(15)」や「(31)」なのか?
「なぜ32ビットではなく31ビットなのですか?」という質問をよく受けます。
これはメインフレームの歴史的経緯が大きく関わっています。かつての汎用機のレジスタ構成上、「最上位ビットは常に符号ビット」として厳格に管理する設計思想があったためです。
31ビット(あるいは15ビット)と宣言することは、プログラマが「このデータは純粋な二進数値としてCPUのレジスタにロードして計算する」とコンパイラに強く意思表示することと同義です。これにより、PL/Iは非常に高速なバイナリ演算を実行できるわけです。
—
最後に:怖がる必要はありません
PL/Iのデータ宣言は、最初は少し独特で難しく感じるかもしれません。しかし、今回紹介した「数値の箱のサイズ」と「溢れた時のケア(ON ユニット)」さえ押さえておけば、あとはメモリの効率を極限まで引き出せる強力な相棒になってくれます。
基幹システムの保守・移行現場では、こうした「基本の箱」の理解が、バグを未然に防ぐ最大の武器になります。もし古いソースコードで謎の `FIXED BIN(31)` を見つけたら、「ああ、4バイトの整数を大切に扱っているんだな」と、優しく見守ってあげてくださいね。
また次回の記事では、「文字列操作の落とし穴」について深掘りしていこうと思います。それでは、良きメインフレームライフを!
