0.9 == 1-0.1 >>> TRUE
0.9 == 1.1-0.2 >>> FALSE
答案 0 :(得分:34)
> 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
我建议你阅读“what every computer scientist should know about floating point numbers”。 (or here)。
Richie也指出R faq mentions this问题。你应该真正阅读整个R FAQ。
您遇到的问题是浮点在大多数情况下不能完全表示小数分数,这意味着您经常会发现完全匹配失败。
当你说:
时,R略有说谎> 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函数实际上是检查数字之间的差异是两个尾数之间最小差异的平方根。
这个算法在称为非正规数的非常小的数字附近有点滑稽,但你不必担心。
答案 1 :(得分:5)
当你想测试两个是否计算时,你需要小心编程 数字相等。 R将假设你的意思是“完全平等”,这意味着什么 取决于机器精度。大多数数字舍入到53位二进制数字精度。 因此,通常情况下,两个浮点数不会可靠地相等,除非它们是 由相同的算法计算,并不总是那么。您可以通过平方看到这一点 2的平方根:当然这些值是一样的吗?
x <- sqrt(2)
x * x == 2
[1] FALSE
我们可以通过减法看出这两个值有多大差异:
1.1 - 0.2 - 0.9
[1] 1.110223e-16