ROUND 関数
第1引数を第2引数の最も近い倍数(第2引数が省略された場合は最も近い整数)に丸めます。
| カテゴリ: | 切り捨て |
|---|---|
| 返されるデータの種類: | DOUBLE |
目次
構文
詳細
- 基本概念
- 2進算術演算と10進算術演算の差異
- 丸めの影響
- 2進値の表現
- 近似等式のテスト
- 期待される結果の生成
- 丸め単位が整数の逆数である場合
- 特殊なケースの計算結果
- 値が丸め単位の倍数の中間にある場合の計算結果
基本概念
ROUND関数は、第1引数を第2引数の倍数の近似値に丸めます。結果は第2引数の正確な倍数でない場合があります。
2進算術演算と10進算術演算の差異
コンピューターは、有限精度の2進算術演算を使用します。通常、厳密な2進表現がない数値を扱う場合、コンピューターによって生成される結果は10進算術演算で生成される結果とわずかに異なります。
たとえば、10進値の0.1および0.3には厳密な2進表現はありません。10進算術演算の3*0.1は厳密に0.3になりますが、2進算術演算ではこの等式は成り立ちません。
次の例が示すように、aがfloatでbがREALの場合、2つの値には差があります。
proc ds2;
data _null_;
dcl float a diff;
dcl real b;
method run();
a=0.3;
b=3*0.1;
diff=a-b;
put a=;
put b=;
put diff=;
end;
enddata;
run;
quit;
次の行がSASログに書き込まれます。
a=0.3 b=0.30000001192092; diff=-1.192092896618E-8
丸めの影響
丸める値に最も近い丸め単位の厳密な倍数を見つけることが丸めの定義となります。たとえば、10進算術演算の場合、0.33を最も近い0.1の倍数に丸めると、3*0.1つまり0.3になります。2進算術演算では0.3が0.1の厳密な倍数ではないため、2進算術演算の場合、0.33を最も近い0.1の倍数に丸めると3*0.1になりますが、0.3にはなりません。
ROUND関数は、数学的に正しい厳密な結果でなくても10進算術演算に基づいて値を返します。ROUND(0.33,0.1)の例では、ROUNDは3*0.1ではなく0.3を返します。
2進値の表現
DS2プログラムで文字"0.3"が定数として示されている場合、値は3/10として計算されます。ROUND(0.33,0.1)は、標準の入力形式にあわせて結果を3/10として計算します。次のステートメントでは期待される結果が生成されます。
if round(x,0.1) = 0.3 then
... more DS2 statements ...
ただし、次のステートメントのように定数0.3のかわりに変数Yを使用する場合、Yの計算方法によっては予期しない結果が生じる可能性があります。
if round(x,0.1) = y then
... more DS2 statements ...
ROUNDが標準の入力形式を使用してYを文字"0.3"として読み込む場合、IFステートメントに定数0.3が示されている場合と同じ結果になります。ROUNDが別の入力形式を使用してYを読み込む場合や、SAS以外のプログラムがYを読み込む場合、文字"0.3"では厳密な3/10の値が生成されない可能性があります。また、厳密な2進表現ではない数値が計算に含まれている場合や、浮動小数点表現が異なる別の動作環境にテーブルを移植する場合も、正確な結果を得られない可能性があります。
Yが小数第1位の10進数だとわかっているが、標準の入力形式で生成される値とまったく同じかどうかわからない場合、次のステートメントを使用することをお勧めします。
if round(x,0.1) = round(y,0.1) then
... more DS2 statements ...
近似等式のテスト
近似等式をテストする一般的な方法としてROUND関数を使用しないでください。最下位ビットのみが異なる2つの数値を丸める場合、一方の数値が切り下げられてもう一方の数値が切り上げられると、異なる値に丸められる可能性があります。近似等式のテストは、数値の計算方法によって異なります。両方の数値が高い相対精度で計算されている場合、次の例のようにABSおよびMAX関数を使用して近似等式をテストできます。
if abs(x-y) <= 1e-12 * max( abs(x), abs(y) ) then
... more DS2 statements ...
期待される結果の生成
通常、ROUND(expression, rounding-unit)は、結果の有効桁数が9以下で、次のどの条件にも該当しない場合、10進算術演算で期待される結果を生成します。
- 丸め単位が整数である。
- 丸め単位が1e-15以上の10のべき乗である。 (脚注 1)
- 10進算術演算で期待される結果が小数第4位以下である。
次に例を示します。
proc ds2;
data rounding(overwrite=yes);
method run();
d1 = round(1234.56789,100) - 1200;
d2 = round(1234.56789,10) - 1230;
d3 = round(1234.56789,1) - 1235;
d4 = round(1234.56789,.1) - 1234.6;
d5 = round(1234.56789,.01) - 1234.57;
d6 = round(1234.56789,.001) - 1234.568;
d7 = round(1234.56789,.0001) - 1234.5679;
d8 = round(1234.56789,.00001) - 1234.56789;
d9 = round(1234.56789,.1111) - 1234.5432;
/* d10 has too many decimal places in the value for */
/* rounding-unit. */
d10 = round(1234.56789,.11111) - 1234.54321;
end;
enddata;
run;
quit;
proc print data=rounding; run;
次の出力は結果を示しています。
丸め単位の値に基づく丸めの結果

丸め単位が整数の逆数である場合
丸め単位が整数の逆数である場合 (脚注 2) ROUND関数は整数で除算して結果を計算します。そのため、丸め単位の倍数ではなく2つの整数の比率を使用してROUNDの結果を比較できます。次に例を示します。
proc ds2;
data rounding2(overwrite=yes);
drop pi unit;
method run();
pi = arcos(-1);
unit=1/7.;
d1=round(pi,unit) - 22/7.;
d2=round(pi, unit) - 22*unit;
end;
enddata;
run;
quit;
proc print data=rounding2;
run;
次の出力は結果を示しています。
整数の逆数による丸めの結果

特殊なケースの計算結果
ROUND関数は、次の条件にすべて該当する場合に丸め単位で整数を乗算して結果を計算します。
- 丸め単位が整数でない。
- 丸め単位が10のべき乗でない。
- 丸め単位が整数の逆数でない。
- 10進算術演算で期待される結果が小数第4位以下である。
次に例を示します。
proc ds2;
data _null_;
method run();
difference=round(1234.56789,.11111) - 11111*.11111;
put difference=;
end;
enddata;
run;
quit;
次の行がSASログに書き込まれます。
difference=0
値が丸め単位の倍数の中間にある場合の計算結果
丸める値が丸め単位の2つの倍数のほぼ中間にある場合、ROUND関数は絶対値を切り上げ、符合を元に戻します。次に例を示します。
proc ds2;
data test(overwrite=yes);
method run ();
do i=8 to 17;
value=0.5 - 10**(-i);
round=round(value);
output;
end;
do i=8 to 17;
value=-0.5 + 10**(-i);
round=round(value);
output;
end;
end;
enddata;
run;
quit;
proc print data=test;
run;
次の出力は結果を示しています。
値が丸め単位の倍数の中間にある場合の丸めの結果

近似は丸める値のサイズに関連し、次の例のように計算されます。このコード例の結果とROUND関数の結果がまったく同じにはならない場合があります。
proc ds2;
data testfile(overwrite=yes);
method run();
do i = 1 to 17;
value = 0.5 - 10**(-i);
epsilon = min(1e-6, value * 1e-12);
temp = value + .5 + epsilon;
fraction = modz(temp, 1);
round = temp - fraction;
output;
end;
end;
enddata;
run;
quit;
proc print data=testfile noobs;
format value 19.16;
run;
比較
ROUND関数はROUNDE関数とほぼ同じですが、第1引数が第2引数の最も近い2つの倍数の中間にある場合にROUNDEが偶数の倍数を返す点が異なります。ROUNDは、絶対値が大きい方の倍数を返します。
ROUNDZ関数は、10進算術演算で計算された結果と結果を一致させようとせずに、丸め単位の倍数を返します。
例
次のプログラムは、ROUND関数によって返される結果とROUNDE関数によって返される結果を比較します。出力は、Windows動作環境で生成されています。
proc ds2;
data results(overwrite=yes);
dcl double x rounde round;
method run();
do x=0 to 4 by .25;
Rounde=rounde(x);
Round=round(x);
output;
end;
end;
enddata;
run;
quit;
proc print data=results;
run;
次の出力は結果を示しています。
ROUND関数とROUNDE関数によって返される結果
