【入門編】BINARYビルトイン関数による型変換 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといったモダン、あるいはちょっとお堅い言語の経験がある方にとって、突然目の前に現れるPL/I(ピーエルアイ)という言語は、まるで古い洋館の扉を開けたときのような、独特の緊張感がありますよね。

特に「データ型」周りの仕様、なかでも今回取り上げる「FIXED BINARY(固定小数点二進数)」と、それを自在に操る`BINARY`ビルトイン関数の挙動は、最初は少し奇妙に映るかもしれません。でも大丈夫です。怖がる必要は全くありません。ボンネットを開けて中身を覗いてみれば、COBOLのCOMP-3やJavaのプリ型とは一味違う、メインフレームならではの合理的な仕組みが見えてきますよ。

それでは、一緒に一つずつ紐解いていきましょう!

—

1. そもそも PL/I の FIXED BINARY ってなに?

Javaなら `int` や `long`、COBOLなら `PIC S9(4) COMP` などにあたるものが、PL/Iの世界では `FIXED BINARY`(略して `FIXED BIN`) です。

ここで初心者がまず躓くのが、宣言時の「精度の指定方法」です。
例えば、COBOL出身のエンジニアだと「9を何桁にするか」で考えがちですが、PL/Iの `FIXED BINARY` は「ビット数(2進数の桁数)」で指定します。

1
DCL WK_COUNT FIXED BIN(15); / 15ビットの固定小数点数 /

「えっ、15ビット?」と思いましたよね。そうなんです。バイト単位ではなく、CPUが計算しやすいビット単位でメモリの領域をガッツリ確保しに行きます。この `FIXED BIN(15)` なら、符号(プラス・マイナス)を含めて約32,767までの数値を扱うことができます。C言語の `short` や Javaの `short` と同じ仲間だとイメージすると、ぐっと親しみが湧くのではないでしょうか。

—

2. 数値を自在に変形させる `BINARY` ビルトイン関数

さて、ここからが本題です。
画面から受け取った文字列や、十進数のデータ(`FIXED DEC`)、あるいは計算途中の数値を、「ちょっと `FIXED BIN` に変換したいな」というときに使うのが `BINARY` ビルトイン関数 です。

書き方の基本形はこうです。

1
BINARY ( 式 [, 精度 [, 拡大縮小係数 ]] )

なんだか数学の関数っぽくて身構えてしまいますが、要するに 「カッコの中のデータを、指定した精度の `FIXED BINARY` に変換してね!」 という命令です。

Javaでいう `(short) 任意の数値` のようなキャスト(型変換)に似ていますが、PL/Iの `BINARY` 関数は、単なる型合わせだけでなく、「桁あふれ(Overflow)」や「端数の丸め・切り捨て」のドラマを裏側でたくさん抱えている、なかなかに味わい深い奴なのです。

—

3. 実例で見る! `BINARY` 関数の挙動と注意点

百聞は一見にしかず。実際のPL/Iコード例を見てみましょう。
レガシーなバッチ処理の中で、十進数の金額データをバイナリのカウンターに変換しているシーンをイメージしてください。

1
DCL WS_DEC_AMT FIXED DEC(7,2) INIT(12345.67); / 十進数の金額(全体7桁、小数2桁) /
DCL WS_BIN_VAL FIXED BIN(31); / 31ビットのバイナリ変数 /
DCL WS_SMALL_BIN FIXED BIN(15); / 15ビットのバイナリ変数 /

/ 1. 普通に大きなバイナリ(31ビット)へ変換する例 /
WS_BIN_VAL = BINARY(WS_DEC_AMT, 31, 0);
/ → 整数部に変換され、安全に格納されます /

/ 2. あえて小さなバイナリ(15ビット)へ押し込む例(ここでドラマが起きる!) /
WS_SMALL_BIN = BINARY(WS_DEC_AMT, 15, 0);

ここがポイント!切り捨てと丸めの罠

上記のコード2番目で、`WS_DEC_AMT`(12345.67というまぁまぁ大きな数字)を、たった15ビット(最大約32,767まで)の `WS_SMALL_BIN` に押し込もうとしています。

  • 値が入るか入らないか問題:

12345 は 32,767 以内なので、辛うじて値は収まります。しかし、元のデータにあった小数部(.67)はどこへ行ったのでしょうか?

  • 小数の扱いの結末:

`BINARY` 関数で精度を指定する際、第3引数(スケーリングファクタ)を省略するか `0` にすると、小数点以下は問答無用で切り捨て(Truncation)されます。四捨五入ではなく、容赦なくバッサリです。結果、`WS_SMALL_BIN` には整数である `12345` が格納されます。

もし、ここで元の数値が `40000.00` だったとしたらどうなるでしょう?
15ビットの表現限界である 32,767 を超えてしまうため、コンパイル時や実行時に「CONVERSION(変換エラー)」や「SIZE(サイズ超過)条件」のシステム例外が発生し、最悪の場合はアベンド(異常終了)の憂き目に遭います。
「レガシーシステムがいきなり落ちた!」というトラブルの原因の多くは、こうした暗黙の型変換やサイズ超過が引き金になっていることが多いのです。

—

4. アーキテクトからの実践アドバイス

他の言語からPL/Iの世界に飛び込んだ方へ、現場で役立つアドバイスをいくつか送ります。

1. 精度のミスマッチを甘く見ない
計算の途中で `FIXED DEC` と `FIXED BIN` を混ぜて使わないこと。PL/Iは賢いので勝手にコンバージョンしてくれますが、その「お節介」が予期せぬパフォーマン低下や、端数誤差の温床になります。型を合わせるときは、必ず `BINARY` 関数等のビルトイン関数を使って意図的にキャストしましょう。
2. デバッグ時は「SIZE」オプションを味方に
コンパイルオプションに `LIMITS` や `SIZE` を有効にしておくことで、万が一のデータあふれ時に即座に検知できるようになります。本番稼働する前に、境界値(最大値付近のデータ)で必ず単体テストを行ってください。

—

おわりに

いかがでしたでしょうか?
PL/Iの `FIXED BINARY` と `BINARY` ビルトイン関数。最初は「ビット数指定なんてめんどくさいな」「切り捨てのルールが厳しそうだな」と感じたかもしれませんが、コンピュータのハードウェア(CPUやメモリ)の構造に直結した、非常に理にかなった仕組みであることが伝われば嬉しいです。

レガシーシステムの移行や改修は、古い仕様との対話の連続です。「なぜこのビット数(精度)になっているのか?」を紐解いていくと、当時のプログラマが限られたリソースの中で絞り出した知恵や工夫が見えてきて、ちょっとしたロマンを感じたりもします。

怖がらなくて大丈夫。一つずつ仕組みを理解していけば、PL/Iはあなたにとって非常に頼もしい相棒になりますよ。それでは、次回のメインフレーム談義でお会いしましょう!

タイトルとURLをコピーしました