可能重复:
为什么这些数字不相等?
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 常见问题解答提到了这个问题。你真的应该阅读整个 R FAQ。
您遇到的问题是浮点数在大多数情况下不能准确表示小数,这意味着您经常会发现完全匹配失败。
而当你说:
> 1.1-0.2
[1] 0.9
> 0.9
[1] 0.9
你可以找出它在十进制中的真实想法:
> sprintf("%.54f",1.1-0.2)
[1] "0.900000000000000133226762955018784850835800170898437500"
> sprintf("%.54f",0.9)
[1] "0.900000000000000022204460492503130808472633361816406250"
你可以看到这些数字是不同的,但表示有点笨拙。如果我们以二进制(好吧,十六进制,这是等效的)查看它们,我们会得到更清晰的图像:
> 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 的两个数字之间的最小可表示差异,就像这样。
我们可以通过查看 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 函数实际上是检查数字之间的差异是两个尾数之间最小差异的平方根。
这个算法在被称为非正规数的极小数附近有点有趣,但你不必担心这一点。
当您想测试两个计算出的数字是否相等时,您在编程时需要小心。R 将假设您的意思是“完全相等”,这意味着什么取决于机器精度。大多数数字四舍五入到 53 位二进制数字精度。因此,通常情况下,两个浮点数不会可靠地相等,除非它们是由相同的算法计算的,而且即使那样也不总是如此。您可以通过对 2 的平方根进行平方来看到这一点:这些值肯定是相同的吗?
x <- sqrt(2)
x * x == 2
[1] FALSE
我们可以通过减法看出这两个值相差多少:
1.1 - 0.2 - 0.9
[1] 1.110223e-16