循環小数の末尾の値が1上がる現象とDECIMALCONVオプションを使った浮動小数点精度向上による解決(ただし9.4)

浮動小数点まわりは常に面倒なことが多いですよね。
基本、ラウンドしとけってことなんでしょうけど、そうはいかない場合もありますよね。

なんで、そうなるのかって理由はよくわかってないんで、浮動小数点に詳しい方に聞いて欲しいですが
とりあえず、以下のコードと出力結果をみてください(ケツ跳ね現象と勝手に命名して、存在は把握してました)

data _null_;
x=28/3;put "28/3=" x;
x=19/3;put "19/3=" x;
x=76/27;put "76/27=" x;
format x best16.;
run;









例えば
 28÷3は9.3333333333333・・と3がずっと続くはずですが、putの結果、ケツが1跳ねて4になっています。
他の2つの結果も全て、小数点の最後が1増加しています。

この謎の尻上がりをラウンドせずに防ぐ方法はあるでしょうか?

実は9.4からDECIMALCONV=オプションというのが追加されました。

デフォルトはoptions decimalconv=compatible;となっていますが、こいつを


options decimalconv=stdieee;とすると、SASのリファレンスの説明によると

============================================================================
DECIMALCONV=システムオプションを STDIEEE に設定した場合、SAS では、IEEE
浮動小数点演算標準 754–2008 を使用して、10 進値の変換とフォーマットが行われま
す。 STDIEEE 引数を使用すると、浮動小数点数の精度と読みやすさが向上します。
場合によっては、より上位の桁を同じフィールド幅で表示することもできます。
w.d、Ew.および Dw.d を含むその他の出力形式も DECIMALCONV=設定の影響
を受ける場合がありますが、変更が最も目立つのは BESTw.出力形式の使用時です。
==============================================================================

まあ、正確に何言ってるかはよくわからんですけど、とにかく精度が増すってことはわかったよってことで

先ほどのコードにオプションをつけて

options decimalconv=stdieee;
data _null_;
x=28/3;put "28/3=" x;
x=19/3;put "19/3=" x;
x=76/27;put "76/27=" x;
format x  best16.;
run;

とすると

結果は








となりました。


すべてのケースにおいて、この方法で問題が回避できるかはわからないんですが、少なくとも悪くはないオプションじゃないかなぁと思いました(処理負荷あがるのかもしれんけど)

より詳しい方がいたら補足して欲しいな~と思いました。

以上



0 件のコメント:

コメントを投稿