SAS

SASでexcelの四捨五入関数を自作する

SASで計算業務をしている人にとって数値の丸めは日常的に実施してますが、SASの数値の丸めは
多くの人にとってなじみ深いexcelのround関数やfixed関数とは仕様が異なります。excelの四捨五入関数のほうがお手軽なので、SASでも同じような関数があればよいのですが、そういうものはないので自作してみました。

SASでの四捨五入方法

値を丸める場合はそれ以上計算を行わないため、末尾の0を反映させるために文字列型として出力することが普通です。

put関数を使用して表示桁をフォーマットで指定すれば一応四捨五入された数値を出力できますが、数値の演算誤差の影響で意図した結果にならない可能性があります。(5.0と表示されているけど実際は4.999999…となっている場合です。)そのため一回round関数で値を丸めてからput関数で文字列型にする手順が一般的ではないかと思います。

SASのround関数はexcelとはことなり、第1引数を第2引数の最も近い倍数に丸めるというものなので、第二引数の指定がexcelとは異なります。

例えば123.123という数値をexcelで四捨五入して小数第二位まで表示する場合、excelの場合は

round(123.123 , 2)

と入力しますが、SASの場合は

round(123.123, 0.01)

と入力します。round関数とput関数の併用であっても厳密には意図した結果になるとは限らないようですが、もしそうなっても値のずれは無視できる程度(他の人にソフトウェアの仕様だといって納得してもらえるくらい)だと思います。

excelの関数を再現する

丸めに関してはexcelの関数のほうがお手軽なので、同じ機能を持つ自作関数を作成してみました。

proc fcmp outlib=work.func.user ; 
function rnd(num, digit) $20; 
   length out fmt $20; 
   fmt=cats("20.", put(digit,8.0)); 
   out=strip(putn(round(num,10**-digit),fmt)); 
   
   return (out); 
endsub; 
quit;

第一引数に丸めたい数値、第二引数に桁数を指定すると数値を四捨五入して指定された桁数にします。
文字列を出力するのでexcelのfixed関数とほぼ同等の関数です。

実際に使ってみます。

data test;
retain a 1234.51627384; 
/* printプロシジャ表示用 */ 
number=put(a,best.); 

do digit=-3 to 6; 
   /* 値を丸める */ 
   round=rnd(a,digit); 
   output; 
end; 

drop a; 
run; 

proc print data=test; 
var number digit round; 
run;

実行結果はこちら

Obsnumberdigitround
11234.5162738-31000
21234.5162738-21200
31234.5162738-11230
41234.516273801235
51234.516273811234.5
61234.516273821234.52
71234.516273831234.516
81234.516273841234.5163
91234.516273851234.51627
101234.516273861234.516274

excelのfix関数で同様の丸め処理を行うと値はちゃんと一致しました。

Excelでの結果