前のページ|次のページ

ROUND関数

第1引数を第2引数の最も近い倍数(第2引数が省略された場合は最も近い整数)に丸めます。

カテゴリ: 切り捨て

構文

必須引数

argument

丸める数値定数、変数または式です。

オプション引数

rounding-unit

丸め単位を指定する正の数値定数、変数または式です。

詳細

基本概念

ROUND関数は、第1引数を第2引数の倍数の近似値に丸めます。結果は第2引数の正確な倍数でない場合があります。

2進算術演算と10進算術演算の差異

コンピュータは、有限精度の2進算術演算を使用します。通常、厳密な2進表現がない数値を扱う場合、コンピュータによって生成される結果は10進算術演算で生成される結果とわずかに異なります。
たとえば、10進値の0.1および0.3には厳密な2進表現はありません。10進算術演算の3*0.1は厳密に0.3になりますが、2進算術演算ではこの等式は成り立ちません。次の例に示すように、これらの2つの値をSASに書き込むと、同じ値のように見えます。ただし、差異を計算すると、値が異なることがわかります。
data _null_;
   point_three=0.3;   
   three_times_point_one=3*0.1;  
   difference=point_three - three_times_point_one;
   put point_three= ; 
   put three_times_point_one= ;
   put difference= ; 
run; 
次の出力がログに書き込まれます。
point_three=0.3 three_times_point_one=0.3 difference=-5.55112E-17
動作環境の情報: 前述の例は、Windows動作環境で実行されています。他の動作環境を使用する場合、結果がわずかに異なる場合があります。

丸めの影響

丸める値に最も近い丸め単位の厳密な倍数を見つけることが丸めの定義となります。たとえば、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進値の表現

SASプログラムで文字"0.3"が定数として示されている場合、値は標準の入力形式で3/10として計算されます。ROUND(0.33,0.1)は、標準の入力形式にあわせて結果を3/10として計算します。次のステートメントでは期待される結果が生成されます。
if round(x, 0.1)=0.3 then 
   ... more SAS statements ...
ただし、次のステートメントのように定数0.3のかわりに変数Yを使用する場合、Yの計算方法によっては予期しない結果が生じる可能性があります。
if round(x, 0.1)=y then 
   ... more SAS statements ...
SASが標準の入力形式を使用してYを文字"0.3"として読み込む場合、IFステートメントに定数0.3が示されている場合と同じ結果になります。SASが別の入力形式を使用してYを読み込む場合や、SAS以外のプログラムがYを読み込む場合、文字"0.3"では厳密な3/10の値が生成されない可能性があります。また、厳密な2進表現ではない数値が計算に含まれている場合や、浮動小数点表現が異なる別の動作環境にデータセットを移植する場合も、正確な結果を得られない可能性があります。
Yが小数第1位の10進数だとわかっているが、標準の入力形式で生成される値とまったく同じかどうかわからない場合、次のステートメントを使用することをお勧めします。
if round(x, 0.1)=round(y, 0.1) then 
   ... more SAS statements ...

近似等式のテスト

近似等式をテストする一般的な方法としてROUND関数を使用しないでください。最下位ビットのみが異なる2つの数値を丸める場合、一方の数値が切り下げられてもう一方の数値が切り上げられると、異なる値に丸められる可能性があります。近似等式のテストは、数値の計算方法によって異なります。両方の数値が高い相対精度で計算されている場合、次の例のようにABSおよびMAX関数を使用して近似等式をテストできます。
if abs(x-y) <= 1e-12 * max(abs(x), abs(y)) then 
   ... more SAS statements ...

期待される結果の生成

通常、ROUND(argument, rounding-unit)は、結果の有効桁数が9以下で、次のいずれかの条件が該当する場合、10進算術演算で期待される結果を生成します。
  • 丸め単位が整数である。
  • 丸め単位が1e-15以上の10のべき乗である。(丸め単位が1よりも小さい場合、ROUNDは、丸め単位の逆数が10のべき乗との違いが最下位から第3または第4ビッドまでであれば、丸め単位を10のべき乗として扱います)。
  • 10進算術演算で期待される結果が小数第4位以下である。
次に例を示します。
data rounding;
   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; 
run;
proc print data=rounding noobs;
run;
丸め単位の値に基づいて丸めた場合の出力結果
丸め単位の値に基づいて丸めた場合の出力結果
動作環境の情報: 前述の例は、Windows動作環境で実行されています。他の動作環境を使用する場合、結果がわずかに異なる場合があります。たとえば、z/OSでは、d10という値は–1.7053E–13です。

丸め単位が整数の逆数である場合

丸め単位が整数の逆数である場合、ROUND関数は整数で除算して結果を計算します。(ROUNDは、丸め単位の逆数と整数の違いが最下位から第3または第4ビッドまでであれば、丸め単位を整数の逆数として扱います。)そのため、丸め単位の倍数ではなく2つの整数の比率を使用してROUNDの結果を比較できます。次に例を示します。
data rounding2;
   drop pi unit;
   pi=arcos(-1);
   unit=1/7;
   d1=round(pi, unit) - 22/7;        
   d2=round(pi, unit) - 22*unit;  
run;
proc print data=rounding2 noobs;
run;
整数の逆数で丸めた場合の出力結果
整数の逆数で丸めた場合の出力結果
動作環境の情報: 前述の例は、Windows動作環境で実行されています。他の動作環境を使用する場合、結果がわずかに異なる場合があります。たとえば、z/OSでは、d2という値は2.2204E-16です。

特殊なケースの計算結果

ROUND関数は、次の条件にすべて該当する場合に丸め単位で整数を乗算して結果を計算します。
  • 丸め単位が整数でない。
  • 丸め単位が10のべき乗でない。
  • 丸め単位が整数の逆数でない。
  • 10進算術演算で期待される結果が小数第4位以下である。
次に例を示します。
data _null_;
   difference=round(1234.56789, .11111) - 11111*.11111;
   put difference=;
run;
次の出力がログに書き込まれます。
difference=0
動作環境の情報: 前述の例は、Windows動作環境で実行されています。他の動作環境を使用する場合、結果がわずかに異なる場合があります。

値が丸め単位の倍数の中間にある場合の計算結果

丸める値が丸め単位の2つの倍数のほぼ中間にある場合、ROUND関数は絶対値を切り上げ、符合を元に戻します。次に例を示します。
data test;
   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;
run;
proc print data=test noobs;
   format value 19.16;
run;
丸め単位の倍数の中間にある値を丸める場合の出力結果
丸め単位の倍数の中間にある値を丸める場合の出力結果
動作環境の情報: 前述の例は、Windows動作環境で実行されています。他の動作環境を使用する場合、結果がわずかに異なる場合があります。
近似は丸める値のサイズに関連し、次のDATAステップのように計算されます。このDATAステップコードの結果とROUND関数の結果がまったく同じにはならない場合があります。
data testfile;
   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;
run;
proc print data=testfile noobs;
   format value 19.16;
run;

比較

ROUND、ROUNDEおよびROUNDZ関数は類似していますが、次の4点が異なります。
  • ROUNDは、第1引数が第2引数の最も近い2つの倍数のほぼ中間にある場合には絶対値が大きい方の倍数を返します。
  • ROUNDEは、第1引数が第2引数の最も近い2つの倍数のほぼ中間にある場合には偶数の倍数を返します。
  • ROUNDZは、第1引数が第2引数の最も近い2つの倍数のちょうど中間にある場合には偶数の倍数を返します。
  • 丸め単位が1よりも小さい場合や整数の逆数でない場合、ROUNDZによって返される結果は10進算術演算の結果と完全には一致しない可能性があります。通常、ROUNDとROUNDEは、結果が10進算術演算に一致するようにファジーと呼ばれる追加の計算を実行します。ROUNDZは、結果をファジー処理しません。

次の例では、ROUND関数によって返される結果とROUNDE関数によって返される結果を比較します。出力は、Windows動作環境で生成されています。
data results;
   do x=0 to 4 by .25;
      Rounde=rounde(x);
      Round=round(x);
      output;
   end;
run;
proc print data=results noobs;
run;
ROUND関数とROUNDE関数によって返される出力結果
ROUND関数とROUNDE関数によって返される出力結果

関連項目:

前のページ|次のページ|ページの先頭へ