先來看看下面這一個簡單的程式和結果。
data test;
input x y;
datalines;
0.54 0.36
54 36
;
data test1;
set test;
pct=((x-y)/y)*100;
if pct=50 then chk=1;
run;
proc print data=test1;
run;
結果如下圖:
明明PCT看起來都是50,為什麼只有第2筆的CHK為1?
data test2;
set test1;
format pct1 32.;
pct1=pct*1000000000000000000;
run;
proc print data=test2;
run;
有沒有發現第1筆資料的PCT其實為50.000000000000016384。
其實這個問題是浮點運算的問題,電腦在運算小數點時候所產生的不精確性(這太專業我也沒辦法說清楚,留給GOOGLE大神解釋吧)。讀者可以閱讀SAS台灣官方網頁所建議的處理方法「SAS數值變數的儲存與運算」,下列文章也可以參考看看。
如何修正浮點算術中的進位誤差(EXCEL)— EXCEL也會有同樣的問題
因此判斷式所用的變數內容「可能有小數」時,最好同時使用截斷函數(Truncation Function)於變數上,常用的截斷函數包括,ROUND(四捨五入)、INT(取整數)、CEIL(無條件捨去)、FLOOR(無條件進位)等,小數點截斷方法可以參考我寫的另一篇「小數點後做無條件捨去或進位」。
重新把判斷式新增截斷函數後,即可得到正確的結果了。
data test3;
set test;
pct=((x-y)/y)*100;
if round(pct,1)=50 then chk=1;
run;
proc print data=test3;
run;
這個問題我已經知道很久了~但也沒想到要寫出來,主要是因為沒有人問過我啊。所以很感佩黃小學妹的細心,她希望這樣經驗應該分享給更多人知道,哪就寫吧,而且最近不小心拿得到一個機械鍵盤,突然愛上打字了~~~希望這次內容對各位有所幫助。
沒有留言:
張貼留言