小数点以下の計算結果は数値フォーマットの種類によって異なる

2024年3月23日はじめてのWebFOCUS

この記事ではWebFOCUSの小数点以下の数値の四捨五入や、内部的な保持イメージを説明しています。

3種類の数値フォーマット

WebFOCUSでは大きい分類として、以下の数値フォーマットがあります。

数値型WebFOCUS
フォーマット
小数点以下の指定除算によって
余りが出た場合
整数I型(Integer)できない表示桁を超えた値は保持しない
パック10進数 P型(Pack) できる表示桁を超えた値は保持しない
浮動小数点数D型(Double)
F型(Float)
できる表示桁を超えた値は保持する

これらのフォーマットの内、パック10進数と浮動小数点数については違いが分かりにくい部分があるため、除算処理と列合計を組み合わせた場合のサンプルにて違いを説明をしていきます。

パック10進数と浮動小数点数の差異

2種類のサンプルを見ていきます。

WebFOCUS では合計行で除算の再計算をする機能もありますが、今回はサンプルとして分かりやすいように単純な明細の合計を表示するものにしています。2種類のサンプルを見ていきます。

サンプル1

3行のデータで「COL1 / COL2」という演算を行っている例です。
縦計では単純に3行のデータを集計していますが、D(浮動小数点数)と P(パック10進数)とで、縦計の結果に違いが出ています。

表示上、DとPは両方とも「33.33」という値ですが、表示桁を超えた場合の内部保持の仕様が異なります。Dは表示上の「33.33」より後ろ値も内部で保持するため実際は「33.3333333…..」のようなイメージですが、Pは表示上も内部的にも「33.33」となっています。

そのため縦計を見ると、Dでは「 33.3333333….. 」を足して「99.9999999….. 」となり、表示上の四捨五入によって「100.00」となっています。Pでは「33.33」が3つ足されて「99.99」となります。

これを「率」として考えた場合は、合計が「100%」となっている方が違和感がありません。

サンプルプロシジャ1

SET PAGE-NUM = NOLEAD
DEFINE FILE GGSALES
 COL1/I4 = 100;
 COL2/I4 = 3;
 END    
TABLE FILE GGSALES
 SUM  
  COL1
  COL2
  COMPUTE D/D8.2 = COL1 / COL2;
  COMPUTE P/P8.2 = COL1 / COL2;
 BY SEQ
 WHERE SEQ LE 3
 ON TABLE SUBTOTAL
END

サンプル2

サンプル1と同じく3行のデータで「COL1 / COL2」という演算を行っている例ですが、数字を少し変えて1000で割ったイメージの例になっています。
D(浮動小数点数)と P(パック10進数)のどちらが良いか考えてみてください。

明細データを1000で割った表現をしているため、縦計を見た時に「P」の列を単純に合計した際は「2325.68」が3つなので「7037.04」で違和感がありませんが、「COL1を1000で割った結果」としては「7037034 / 1000 = 7037.034 」なので、四捨五入後の期待する値は「7037.03」だと思いますので、想定と違ってしまいます

一方、「D」の場合は P とは逆の結果で列を単純に合計した際は結果が違っているように見えますが、縦計を1000で割った値としては期待値です

サンプルプロシジャ2

SET PAGE-NUM = NOLEAD
DEFINE FILE GGSALES
 COL1/I9 = 2345678;
 COL2/I4 = 1000;
 END    
TABLE FILE GGSALES
SUM  
  COL1
  COL2
  COMPUTE D/D8.2 = COL1 / COL2;
  COMPUTE P/P8.2 = COL1 / COL2;
 BY SEQ
 WHERE SEQ LE 3
 ON TABLE SUBTOTAL
END

数値フォーマットの選択に悩んだ時

どちらの数値フォーマットを利用するべきか悩んだ時には、結果の分かりやすい「P」を利用することを推奨しておりますが、細かい仕様に関しては以下に記載します。

Pタイプ(迷ったらこちらを利用する)

  1. パック10進数データ形式として数値が保持されます
    • 明細レコードの集計結果と集計コマンドによる集計結果が一致します
    • 四捨五入を行った場合、指定桁数より小さい値を切り捨てます
  2. 有効桁数は31桁です
    • 整数の桁数が多い場合には、Pタイプを利用します
    • 計算項目に指定する場合、P17以上で四倍精度浮動小数点数演算が行われます
      (小数点以下の数値を利用する場合は、P17以上を指定することが推奨です)
  3. 3桁区切りのカンマは付きません
    • カンマを付けたい場合は、編集オプションの「C」を付与します(例:P17C)

Dタイプ

  1. 浮動小数点数データ形式として数値が保持されます
    • 表示上は四捨五入表示になりますが、内部的な値を一致しない場合があります
      そのため、明細レコードの集計結果と集計コマンドによる集計結果が必ずしも一致しません
    • 四捨五入を行った場合、指定桁数より小さい値は内部的に保持します
      循環小数の場合は、四捨五入の結果がズレる場合があります
      (浮動小数点数の2進数表現で仮数部の53bit目が0となる場合)
  2. 有効桁数は15桁です(Pタイプの方が大きい桁を扱うことができます)
  3. 3桁区切りのカンマは付きます。
    • カンマを外したい場合は、編集オプションの「c」を付与します(例:D15c)

Fタイプ

Dタイプに包含されるため、Fタイプは利用しません