重複の可能性:
これらの数値が等しくないのはなぜですか?
0.9 == 1-0.1 >>> TRUE
0.9 == 1.1-0.2 >>> FALSE
> 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 と呼ばれる非常に小さな数の近くでは少しおかしくなりますが、それについて心配する必要はありません。
計算された 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