我輩はブロガーではない。ネタもまだない

SASとかDelphiあたりの人様の役に立たないネタを提供します

小数の精度

なんでこんな計算してるのかわからないプログラムが手元にありました。
(多分SAS xptのバイナリ解析のためのデータを生成していたんだと思います)

data float;
  length num 8;
  num= (10.123)**4;
  output;
run;

で、なんでそんなことしたのかわからないのですが、x86互換モードとx64 nativeモードのsasで実行すると、以下のような結果になりました。
SAS xptファイルにバイナリレベルの差があるか比較するためだったと思います。わかってんじゃねーか!

f:id:japelin:20210406160425p:plain
x86とx64で作成されたデータセットの比較結果

むむむっ。一致していない…



小数桁が多そうなので、数値フォーマット「24.16」とバイナリ「hex16.」で出力して値を確認します。

f:id:japelin:20210406160624p:plain
x86でログに出力された値
f:id:japelin:20210406160708p:plain
x64でログに出力された値


数値としては同じようですが、バイナリレベルでは違いがあることが分かります。
以下によると、SASではまず、2進法に書き換え、整数部分が1以上10未満になるように桁をずらし…(中略)、8バイトの数値が出来上がります。
SASにおける数値の正確さ

この8バイトは、あくまでもSASが数値を格納するために確保するバイトであり、OSやSASの実行モードである32bit、64bitは関係無いのですが、おそらく途中の計算精度で32bitが影響して、差が出てしまっているんだろうと思われます。

なお、以下には、さらっと重要なことが書いてあります
SAS9.3出力形式と入力形式
d の値が 15 より大きい場合、有効桁数 15 桁以降の桁の小数値が正確でない場合があります。

え、まじで?
手元にダウンロードしてあったSAS9.4のリファレンス(2013年)にも同じ記載がありました。
一方で、オンラインドキュメントには何も記載はありません。

ちなみに、SAS on DEMAND for Academics(SAS Studio)で実行すると、64bit環境と同じ結果が得られました。

f:id:japelin:20210406163825p:plain
SAS ODAでの実行結果


データセットをマージなりすれば差を計算できますが、一見わかりません。
32bit環境から64bit環境に移行した解析プログラムで丸めが行われていないと(そんなわけ無いですよねぇ、皆さん)、怖い思いをしそうです。