这两个比较之间有什么区别? [英] What is the difference between these two comparisons?
问题描述
可能重复:
为什么这些数字不相等?
Possible Duplicate:
Why are these numbers not equal?
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
明智人的答案:
我建议您阅读"每位计算机科学家都应了解的浮点数". (或在此处).
Also Richie points out that the R faq mentions this issue. You should really read the whole of the R FAQ.
您遇到的问题是,在大多数情况下,浮点数不能完全代表十进制小数,这意味着您经常会发现精确匹配失败.
The problem you have encountered is that floating point cannot represent decimal fractions exactly in most cases, which means you will frequently find that exact matches fail.
当您说:R时,R稍微偏下
while R lies slightly when you say:
> 1.1-0.2
[1] 0.9
> 0.9
[1] 0.9
您可以找出十进制的含义:
You can find out what it really thinks in decimal:
> sprintf("%.54f",1.1-0.2)
[1] "0.900000000000000133226762955018784850835800170898437500"
> sprintf("%.54f",0.9)
[1] "0.900000000000000022204460492503130808472633361816406250"
您可以看到这些数字不同,但是表示有点笨拙.如果我们以二进制(十六进制,等效)的形式查看它们,则会得到更清晰的画面:
You can see these numbers are different, but the representation is a bit unwieldy. If we look at them in binary (well, hex, which is equivalent) we get a clearer picture:
> 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的两个数字之间最小的可表示差异.
You can see that they differ by 2^-53
, which is important because this number is the smallest representable difference between two numbers whose value is close to 1, as this is.
我们可以通过在R的计算机字段中查找任何给定的计算机,这个最小的可表示数字是什么:
We can find out for any given computer what this smallest representable number is by looking in R's machine field:
> ?.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"
您可以使用此事实来创建一个几乎等于"函数,该函数检查差值是否接近浮点数中最小的可表示数字.实际上,这已经存在(感谢评论者).
You can use this fact to create a 'nearly equals' function which checks that the difference is close to the smallest representable number in floating point. In fact this already exists (thanks to the commenter).
> ?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函数实际上是在检查数字之间的差是否是两个尾数之间最小差的平方根.
So the all.equal function is actually checking that the difference between the numbers is the square root of the smallest difference between two mantissas.
这种算法在称为反常态的极小数附近非常有趣,但是您不必为此担心.
This algorithm goes a bit funny near extremely small numbers called denormals, but you don't need to worry about that.
这篇关于这两个比较之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!