【发布时间】:2011-01-14 17:24:11
【问题描述】:
【问题讨论】:
标签: r floating-accuracy
【问题讨论】:
标签: r floating-accuracy
> 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 常见问题解答。
您遇到的问题是浮点数在大多数情况下不能准确表示小数,这意味着您会经常发现完全匹配失败。
而当你说:
> 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 函数实际上是检查数字之间的差是两个尾数之间最小差的平方根。
这个算法在被称为非正规数的极小数附近有点有趣,但你不必担心。
【讨论】:
abs 而不是 fabs。或者可能是isTRUE(all.equal(a, b))。
当你想测试两个计算是否被计算时,你需要小心编程 数相等。 R 会假设你的意思是“完全相等”,这意味着什么 取决于机器精度。大多数数字四舍五入到 53 位二进制精度。 因此,通常两个浮点数不会可靠地相等,除非它们是 由相同的算法计算,即使那样也不总是。你可以通过平方看到这个 2 的平方根:这些值肯定是相同的吗?
x <- sqrt(2)
x * x == 2
[1] FALSE
我们可以通过减法看出这两个值相差多少:
1.1 - 0.2 - 0.9
[1] 1.110223e-16
【讨论】: