他の言語は詳しくないのでわかりませんが、SASにおいても、ある程度知っておかないと、直感では理解不能な現象に直面します。
今、以下のようなデータセットがあるとします。
data Q1;
A=0.2;B=0.1;output;
A=0.3;B=0.2;output;
run;
AからBを引いて、Cという変数に割り当てます
data Q2;
set Q1;
C=A-B;
run;
それがどおした?当たり前じゃないかという感じですが、
知っている人は既にピンときているはず。
Cが0.1であれば変数FLに'Y'、それ以外は'N'をいれます。
data Q3;
set Q2;
if C=0.1 then FL='Y';
else FL='N';
run;
当然、Cは2レコードとも0.1なわけだから、FLはYになると思いきや、、、
とまあ、こういうことになるんです。
これは、見た目に同じ0.1でも実は内部的に10の何乗分の1ぐらいの、超小さい部分で誤差が生じているんですね。
なんで、0.2-0.1と0.3-0.2みたいな小学生でもできる計算で誤差が生じるのかというと、SASが内部的に2進法に変換して計算しているため、パターンによって10進法に戻すときに微細な誤差がでちゃうんですね。
ごめんなさい、感覚で覚えているので、詳しい理屈は詳しい方に聞いてください。
見た目、両方、0.1じゃん!と思った方は
data Q4;
set Q3;
D=C;
format D HEX16.;
run;
のように例えば16進数のフォーマットを当ててみると
あ、確かになんか違う!って感じです。
この現象が往々にして猛威をふるいます。
if文などの条件分岐がこけたり、コンペアが一致しなかったり、ソート順がおかしく見えたりするわけです。
対応策としては、roundで
data Q5;
set Q2;
if round(C,0.00001)=0.1 then FL='Y';
else FL='N';
run;
適当に余裕をもって丸めるとかの
原始的処理になります。
まあ、コンピューターってそういうもんだとは思いますが、何とかならないですかね、、、。
0 件のコメント:
コメントを投稿