10

The R Infernoを読んでいて、わからないことがありました。Inferno のセクション 8.2.23 に加えて、浮動小数点数の比較に関する良い質問がいくつかあります: question1question2

しかし、私はまだ使用中に問題が発生していall.equalます。デフォルトall.equalを使用すると、(ほとんど)期待どおりの結果が得られます。

> all.equal(2,1.99999997)
[1] "Mean relative difference: 1.5e-08"
> all.equal(2,1.99999998) #I expected FALSE here
[1] TRUE
> all.equal(2,1.99999999)
[1] TRUE

1.99999998 で関数がTRUEを返す理由はわかりませんが、許容レベルを指定した次の動作ほど問題ではありません。

> all.equal(2,1.98,tolerance=0.01) #Behaves as expected
[1] "Mean relative difference: 0.01"
> all.equal(2,1.981,tolerance=0.01) #Does not behave as expected
[1] TRUE

さらに、

> all.equal(2,1.980000000001,tolerance=0.01)
[1] TRUE 

しかし、計算すると:

> diff(c(1.981,2))
[1] 0.019

そして明らかに、

> diff(c(1.981,2)) >= 0.01
[1] TRUE

では、なぜall.equal公差 0.01 で 2 と 1.981 を区別できないのでしょうか?

編集

ドキュメントから: scale = NULL (デフォルト) の数値比較は、最初に 2 つの数値ベクトルの平均絶対差を計算することによって行われます。これが許容値よりも小さいか有限でない場合は、絶対差が使用されます。それ以外の場合は、相対差が平均絶対差でスケーリングされます。

ここでは、動作がわかりません。diff(1.981,2)有限ではないことがわかります:

> sprintf("%.25f",diff(c(1.981,2)))
[1] "0.0189999999999999058530875"

しかし、それは何によってスケーリングされるのでしょうか? 各ベクトルの長さが 1 の場合、平均絶対差は 2 つの数値の差に等しくなければならず、平均絶対差で割ると 1 になります。明らかに、ここでの論理が間違っていることを理解しています。

4

2 に答える 2

7

これは、浮動小数点の精度に関係しています。マニュアルは一見すると完全に明確ではありませんが、あなたの例では、mean absolute differenceof2-1.9810.019which is > 0.01、 the tolerance. scaleもございNULLます。したがって、行われる比較は、平均絶対差でスケーリングされた相対差です。えっ!?

を使用toleranceすることは、関係する数値の大きさを気にすることを意味します。相対差は、差がどれだけ大きいか (絶対項) ではなく、比較対象の数値と比較してどれだけ大きいかを説明します。リンクの例を考えると、 5 と 6 の違いは、 と の間よりも重要です(私はこの用語を大まかに使用しています) 。1,000,000,0001,000,000,001

したがって、2 つの数値の相対的な差が小さい場合tolerance、数値は等しいと見なされます。(この例のように) 2 つの単一の数値の場合、相対差は次のようになります。

( current - target ) / current

どれが

( 2 - 1.981 ) / 2 == 0.0095

したがって、指定した許容0.01差は、相対差がこれよりも小さいため、数値は等しいと見なされます。これらの数値±の差は、相対的な差でもあり、たまたま表現可能な最小の浮動小数点数です!

identical( abs( ( 2 - 0.0095 ) - ( 1.981 + 0.0095 ) ) , .Machine$double.eps )
[1] TRUE

今試してください:

all.equal( 2 , 1.981 , 0.00949999999999 )
[1] "Mean relative difference: 0.0095"
于 2013-09-13T21:36:26.597 に答える
6

これは、この場合、all.equal相対的な差異をチェックするために発生します。を設定した場合scale=1、つまりスケーリングなしの場合、絶対比較が行われ、all.equal期待どおりに動作します。

詳細については、scaleパラメータに関するドキュメントを参照してください。

> all.equal(2,1.980000000001,tolerance=0.01)
[1] TRUE
> all.equal(2,1.980000000001,tolerance=0.01,scale=1)
[1] "Mean scaled difference: 0.02"
于 2013-09-13T20:01:47.090 に答える