10

重複の可能性:
これらの数値が等しくないのはなぜですか?

0.9 == 1-0.1 >>> TRUE
0.9 == 1.1-0.2 >>> FALSE
4

2 に答える 2

36

プログラムを修正するための回答:

> all.equal(0.9,1.1-0.2)
[1] TRUE
> all.equal(0.9, 1.1-0.3)
[1] "Mean relative difference: 0.1111111"
> isTRUE(all.equal(0.9, 1.1-0.3)
[1] FALSE

コードで使用する場合:

if(isTRUE(all.equal(0.9,1.1-0.2)) {
   ....
}

またはベクトルで:

> vec1=0.9
> vec2=c(1.1-0.2,1.3-0.4,1.0-0.2)
> mapply(function(...)isTRUE(all.equal(...)),vec1, vec2)
[1]  TRUE  TRUE FALSE

賢明な人々への答え:

「すべてのコンピューター科学者が浮動小数点数について知っておくべきこと」を読むことをお勧めします。(またはここ)。

また Richie は、 R faq がこの問題に言及していることを指摘しています。R の FAQ 全体を実際に読む必要があります。

マゾヒストへの回答:

あなたが遭遇した問題は、ほとんどの場合、浮動小数点は小数を正確に表すことができないということです。つまり、正確な一致が失敗することがよくあることを意味します。

あなたが言うとき、Rは少し嘘をつきます:

> 1.1-0.2
[1] 0.9
> 0.9
[1] 0.9

10 進数で実際に何を考えているかを確認できます。

> sprintf("%.54f",1.1-0.2)
[1] "0.900000000000000133226762955018784850835800170898437500"
> sprintf("%.54f",0.9)
[1] "0.900000000000000022204460492503130808472633361816406250"

これらの数値が異なることがわかりますが、表現が少し扱いに​​くいです。それらを 2 進数 (まあ、16 進数、同等) で見ると、より明確な図が得られます。

> sprintf("%a",0.9)
[1] "0x1.ccccccccccccdp-1"
> sprintf("%a",1.1-0.2)
[1] "0x1.ccccccccccccep-1"
> sprintf("%a",1.1-0.2-0.9)
[1] "0x1p-53"

この2^-53数値は、値が 1 に近い 2 つの数値の表現可能な最小の差であるため、重要です。

R のマシン フィールドを調べることで、任意のコンピューターについて、この表現可能な最小数が何であるかを調べることができます。

 > ?.Machine
 ....
 double.eps  the smallest positive floating-point number x 
 such that 1 + x != 1. It equals base^ulp.digits if either 
 base is 2 or rounding is 0; otherwise, it is 
 (base^ulp.digits) / 2. Normally 2.220446e-16.
 ....
 > .Machine$double.eps
 [1] 2.220446e-16
 > sprintf("%a",.Machine$double.eps)
 [1] "0x1p-52"

この事実を使用して、差が浮動小数点で表現可能な最小数に近いことを確認する「ほぼ等しい」関数を作成できます。実際、これはすでに存在します(コメント者に感謝します)。

> ?all.equal
....
all.equal(x,y) is a utility to compare R objects x and y testing ‘near equality’.
....
all.equal(target, current,
      tolerance = .Machine$double.eps ^ 0.5,
      scale = NULL, check.attributes = TRUE, ...)
....

> all.equal(0.9,1.1-0.2)
[1] TRUE

したがって、 all.equal 関数は、数値の差が 2 つの仮数の最小差の平方根であることを実際にチェックしています。

このアルゴリズムは、denormals と呼ばれる非常に小さな数の近くでは少しおかしくなりますが、それについて心配する必要はありません。

于 2010-02-09T09:55:14.720 に答える
5

計算された 2 つの数値が等しいかどうかをテストする場合は、プログラミングに注意する必要があります。R は、「正確に等しい」という意味であると想定し、それが何を意味するかはマシンの精度に依存します。ほとんどの数値は、2 進数で 53 桁の精度に丸められます。したがって、通常、2 つの浮動小数点数は、同じアルゴリズムで計算されない限り、確実に等しくなるとは限りません。これは、2 の平方根を 2 乗するとわかります。これらの値は同じですか?

x <- sqrt(2)
x * x == 2
[1] FALSE

減算により、2 つの値がどの程度異なるかを確認できます。

1.1 - 0.2 - 0.9
[1] 1.110223e-16
于 2010-02-09T09:13:18.863 に答える