こんにちは!IBMメインフレームの世界へようこそ。
JavaやCOBOLでの開発経験がおありの方なら、汎用機というだけで「なんだか難しそう…」「古い仕様で頭がこんがらがっちゃいそう…」なんて、少し身構えてしまうかもしれませんよね。でも、どうか安心してください。私たちが普段使っているプログラミング言語の基本が分かっていれば、PL/I(ピーエルワン)も怖くありません。一つずつ蓋を開けて中身を覗いていけば、「ななんだ、こういうことね!」とスッキリ腑に落ちるはずです。
今回は、そんなPL/Iのデータ制御の中でも、バッチ処理やデータ移行の現場で最も頻繁に顔を出す「FIXED BINARY(15)と(31)の内部表現」について、おしゃべりするような感覚でじっくり紐解いていきましょう。
—
1. 他言語からの挑戦者たちが最初に戸惑う「整数」の話
Javaであれば `short` や `int`、COBOLであれば `PIC S9(4) COMP` や `PIC S9(9) COMP` に相当するものが、PL/Iにおける固定小数点二進数(FIXED BINARY)です。
PL/Iの世界では、数値をメモリ上にどう並べるかをプログラマがかなり直感的に(時には厳密に)指定できます。ここで登場するのが、今回の主役である `FIXED BINARY(15)` と `FIXED BINARY(31)` です。
なんだか暗号みたいな名前ですが、カッコの中の数字の意味が分かれば一発で理解できますよ。
- `FIXED BINARY(15)` : 2バイト(16ビット)の整数コンテナ
- `FIXED BINARY(31)` : 4バイト(32ビット)の整数コンテナ
「あれ? 15桁や31桁じゃないの?」と思いませんでしたか?
ここがJavaやCOBOLの感覚でいると最初にハマる罠なんです。PL/Iのカッコの中の数字は「桁数(プレシジョン)」ではなく、「符号を除いた有効ビット数(あるいは全体のビット数)」を指定しているのです。
—
2. メモリの中身を覗いてみよう!符号ビットの仕組み
では、この2バイトと4バイトの箱(ストレージ)の中で、数値と「プラス・マイナス」の符号がどのように扱われているのか、イメージしやすい例えでお話ししますね。
FIXED BINARY(15) (2バイト=16ビットの世界)
旅館の客室を思い浮かべてみてください。全部で16部屋(16ビット)ある小さな温泉宿です。
この宿では、一番左端の部屋(第0号室)を「おカマ番(フラグ専用部屋)」と決めました。
- 一番左の部屋の電気が「消灯(0)」なら:プラス(またはゼロ)
- 一番左の部屋の電気が「点灯(1)」なら:マイナス
これが「符号ビット」の正体です。
残りの15部屋(第1号室〜第15号室)だけで、数値を表現します。だから `(15)` なのですね。
- 表現できる範囲:
- プラス側は $2^{15} – 1$ まで、つまり `32,767` まで。
- マイナス側は $-2^{15}$ まで、つまり `-32,768` まで。
Javaの `short` 型や、COBOLの `COMP`(半ワード)と全く同じお行儀の良い子たちです。
FIXED BINARY(31) (4バイト=32ビットの世界)
こちらは少し大きめのホテルです。全部で32部屋(32ビット)あります。
ルールは同じで、一番左端の部屋(第0号室)が符号専用のお部屋になります。残りの31部屋で数字を表現します。
- 表現できる範囲:
- プラス側は約 `21億(2,147,483,647)` まで。
- マイナス側は約 `-21億(-2,147,483,648)` まで。
Javaの `int` 型や、COBOLの `COMP`(フルワード)の仲間ですね。基幹システムの売上金額や、膨大なループ回数を数えるカウンターには、大体この `FIXED BINARY(31)` が選ばれます。
—
3. 実務で役立つPL/Iコード例と注意点
実際のPL/Iのプログラム(ソースコード)では、これらのデータがどのように宣言され、使われているのでしょうか。簡単なサンプルを見てみましょう。
————————————————————–
- 修正プログラム:FIXED BINARYの宣言と演算のサンプル
————————————————————–
DEMO_PROG: PROC OPTIONS(MAIN);
— 2バイト整数(小さなカウンターやコード値など) —
DCL WK_SMALL_CNT FIXED BINARY(15) INIT(0);
— 4バイト整数(金額や件数など大きな数値) —
DCL WK_TOTAL_AMT FIXED BINARY(31) INIT(0);
— 画面やログ出力用の文字型ワーク —
DCL OUT_MSG CHARACTER(80);
- 1. データの加算処理
WK_SMALL_CNT = WK_SMALL_CNT + 100;
WK_TOTAL_AMT = WK_TOTAL_AMT + 123456789;
- 2. データのオーバーフロー(溢れ)に注意!
- FIXED BINARY(15) に 32,767 を超える値を入れようとすると
- コンパイラや実行時エラー、あるいは予期せぬサイレントデータ破損の原因に!
IF WK_SMALL_CNT > 30000 THEN
DO;
PUT SKIP LIST(‘警告:小規模カウンターが上限に近づいています。’);
END;
RETURN;
END DEMO_PROG;
💡 ここが現場の知見!先輩からのアドバイス
マイグレーションやリプレイスの際、COBOLの `PIC S9(4)` からPL/Iへ移行するケースによく遭遇します。
ここでうっかり、PL/I側で `FIXED BINARY(16)` と書いてしまう人がたまにいます。「16ビットだから16だろ!」と直感で書いてしまうのですが、これは大間違いです。
先ほどお伝えした通り、PL/Iのカッコ内は「符号を除いたビット数」です。
もし `FIXED BINARY(16)` と書いてしまうと、コンパイラは「符号1ビット + データ16ビット = 合計17ビット(あれ、中途半端な…)」と解釈するか、あるいは内部的に特殊な拡張(あるいはコンパイルエラー)を引き起こします。必ず「2バイトなら15」「4バイトなら31」と覚えておいてくださいね。
—
おわりに
いかがでしたでしょうか?
「FIXED BINARY(15) と (31)」と言われると難解なシステム用語に聞こえますが、要するに「2バイトの箱か、4バイトの箱か。そして一番左の部屋をプラスマイナスの旗揚げに使っているだけ」なのです。
レガシーシステムのソースコードを読むとき、変数の定義が目に入ったら、「あ、ここは2バイトの箱だな」「ここは21億まで入る4バイトの箱だな」と、頭の中でスッとメモリの絵が浮かぶようになれば、あなたも立派なPL/I使いの仲間入りです。
これからも怖がらず、一つひとつ紐解いていきながら、メインフレームの海を一緒に泳いでいきましょう!
