【PL/I学習|豆知識】10進精度の「奇数・偶数」パディングの原理とメモリ効率の最適化

導入

メインフレームのCOBOLやPL/Iでデータ定義を行う際、何気なく指定している「桁数(精度)」。実は、この精度設定がメモリ消費量や物理的なデータ配置に直結していることをご存知でしょうか。特にパック10進数(COMP-3)において、偶数精度と奇数精度ではデータの持ち方が異なります。この仕組みを理解していないと、データ移行時の読み取りエラーや、意図しないメモリ浪費を招くことになります。今回は、この「パディング」の原理について解説します。

基礎知識

パック10進数は、1バイトに2つの数値を「ニブル(4ビット)」単位で格納し、最後のニブルに符号(+や-)を保持する形式です。
計算式として「バイト数 = (桁数 + 1) ÷ 2 (端数切り上げ)」が適用されます。
ここで重要なのは「偶数精度」を指定した場合です。例えば6桁(DEC(6))を指定すると、計算上は「7桁分の領域(4バイト)」が確保されます。この時、先頭の1ニブル(4ビット)は「0」で埋められ、これが「パディング」となります。一方、7桁(DEC(7))も同じく4バイトですが、こちらは全ビットを有効に使い切るため、効率が良いとされています。

実装/解決策

物理レイアウトを設計する際は、可能な限り「奇数精度」を選択することで、パディングによる空きニブルの発生を防ぎます。
もし、既存のCOBOL資産で偶数精度が定義されている場合は、後続カラムのオフセットが4ビット(0.5バイト)ズレて認識されるリスクがあるため、COPY句やDSECTでのマッピング時に、この「隠れた4ビット」を厳密に考慮する必要があります。

サンプルプログラム

以下は、PL/Iにおける定義例です。メモリ効率の違いを検証するためのコードです。

/
PACKED DECIMALのメモリ効率比較サンプル
DEC(6)は計算上4バイト消費しますが、先頭4ビットがパディングとして無駄になります。
/

DCL V_SIX FIXED DEC(6); / 6桁: 内部的には7桁分確保され、先頭4ビットは常に0 /
DCL V_SEVEN FIXED DEC(7); / 7桁: 4バイトをフル活用するためメモリ効率が良い /

/
検証用コード:
実際に格納される際の内部構造を意識した代入処理例
/
V_SIX = 123456; / 内部表現: 01 23 45 6C (Cはプラス符号) /
V_SEVEN = 1234567; / 内部表現: 12 34 56 7C /

PUT SKIP LIST(‘V_SIXのメモリ消費: ‘, STG(V_SIX), ‘バイト’);
PUT SKIP LIST(‘V_SEVENのメモリ消費: ‘, STG(V_SEVEN), ‘バイト’);

応用・注意点

現場での移行プロジェクトでは、「物理的なバイト数」と「論理的な桁数」の不一致がトラブルの元になります。特に、JavaやC言語などの外部システムとバイナリデータを連携させる場合、偶数精度のパック10進数をそのまま読み込もうとすると、上位4ビットの「0」が無視され、数値が正しく解釈されないことがあります。
基本的には「奇数精度での統一」を推奨しますが、どうしても偶数精度が必要な場合は、マッピング定義において「空きニブル」を明示的にスキップする処理を組み込むか、変換ルーチンを通すなどの回避策を徹底してください。

コメント

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