メインフレームの世界へようこそ!PL/Iの浮動小数点と「精度の迷宮」を攻略する
こんにちは。メインフレームの深淵を覗き込み、長年PL/Iと共に生きてきたシステムアーキテクトです。
JavaやCOBOLから来た皆さんが、PL/Iのコードを初めて見たとき、「`DCL A FLOAT BIN(53);`」なんて宣言に出会って面食らう姿が目に浮かびます。「数値型なんてCOBOLなら`COMP-3`だけでいいじゃないか!」と思いたくなりますよね。
でも、安心してください。PL/Iは「汎用(Programming Language One)」という名の通り、科学技術計算から事務処理までを一本の言語で書ききるために、非常に柔軟なデータ型を持っています。今回は、ビジネスロジックの落とし穴になりやすい「FLOAT BINARY」と「FLOAT DECIMAL」の精度と丸め誤差について、現場の知見を交えて紐解いていきましょう。
—
1. なぜ「浮動小数点」は計算がズレるのか?
まず、浮動小数点数(FLOAT)を扱う上で絶対に覚えておいてほしいのは、「コンピュータは10進数の小数を、2進数で完璧に表現できないことがある」という事実です。
例えば「0.1」という数字。これを2進数で表そうとすると、「0.0001100110011…」と無限ループに陥ります。これを決まったビット数で切り取って格納するため、計算のたびに微小な誤差(丸め誤差)が積み重なります。
PL/Iの「型」の使い分け
PL/Iでは、大きく分けて2つの浮動小数点型があります。
- FLOAT DECIMAL: 10進数で精度を指定。事務計算の延長線上にあり、直感的に分かりやすい。
- FLOAT BINARY: 2進数で精度を指定。内部的な演算効率が高く、IBMメインフレームのハードウェアの特性を活かせる。
ここで注意!
Javaの`double`(IEEE 754)に慣れている方は、`FLOAT BINARY(53)`が馴染み深いかもしれません。しかし、古いメインフレームのシステムでは、独自のIBM形式浮動小数点を使っていることもあります。マイグレーション時には、この「ビット表現の違い」が思わぬ金額誤差を生むことがあり、現場ではこれを「精度の迷宮」と呼んでいます。
—
2. 実践:PL/Iで数値を定義してみよう
では、実際にプログラムの構造を確認しながら、データ宣言の書き方を見ていきましょう。
1
/
- MAINプログラムの基本構造
- PACKAGEで括り、PROCEDURE OPTIONS(MAIN)でエントリポイントを定義します
/
TEST_PROG: PACKAGE;
/ 10進精度の定義: 桁数を指定 /
DCL VAL_DEC FLOAT DEC(15);
/ 2進精度の定義: ビット数を指定 (53なら倍精度相当) /
DCL VAL_BIN FLOAT BIN(53);
TEST_PROC: PROCEDURE OPTIONS(MAIN);
VAL_DEC = 1.1;
VAL_BIN = 1.1;
/ 実際に計算して比較してみると…誤差が出るかもしれません /
IF ABS(VAL_DEC – VAL_BIN) > 1E-10 THEN
PUT SKIP LIST(‘計算結果にズレが発生しました!’);
END TEST_PROC;
END TEST_PROG;
現場からのアドバイス
事務処理のロジックを組む際、「金額計算にFLOATを使ってはいけない」というのはエンジニアの鉄則です。PL/Iであれば、固定小数点の`FIXED DECIMAL(15, 2)`を使うのが正解です。
FLOATを使うのは、「統計解析」や「複雑な金利計算の係数」など、どうしても精度を犠牲にしても速度や範囲が必要な場合だけに限定しましょう。
—
3. 怖くない!「丸め誤差」との付き合い方
もし、現行のレガシーコードで「なぜか合計金額が1円合わない」というバグに直面したら、以下の手順でチェックしてみてください。
1. データ型の確認: `FLOAT`型が混じっていないか? 混じっているなら、それは本当に`FLOAT`である必要があるか?
2. 精度の確認: `FLOAT BIN(21)`(単精度相当)と`FLOAT BIN(53)`(倍精度相当)が混在して計算されていないか?(暗黙の型変換で精度が落ちているケースが非常に多いです)
3. 比較演算の工夫: `IF A = B THEN` と書かず、`IF ABS(A – B) < 0.001 THEN` のように、「許容誤差」を持たせた比較をする。
---
最後に:メインフレームは「計算機」の原点
メインフレームにおけるPL/Iは、非常に厳格なようでいて、実はプログラマの意図を汲み取ろうとする懐の深い言語です。今回紹介した浮動小数点の扱いは、現代のWeb開発とは少し毛色が違いますが、「コンピュータが内部でどうやって数値を扱っているか」という本質を学べる素晴らしい教材でもあります。
「なんか難しそうだな」と身構えず、まずは小さなプログラムで値を`PUT SKIP LIST`して、計算結果がどう変化するか遊んでみてください。そうやって一つずつ紐解いていけば、皆さんも必ずPL/Iをマスターできますよ。
次回の記事では、`STRUCTURE`(構造体)を使ったデータの受け渡しや、`COBOL`との連携(`INTERLANGUAGE COMMUNICATION`)について深掘りしていこうと思います。それでは、また現場でお会いしましょう!
