seq和==运算符的神秘行为。一个精确的问题?

时间:2012-07-31 14:35:20

标签: r precision seq

我遇到了函数seq的某种奇怪(或者只是没有预期?)的行为。 创建简单序列时,某些值无法与==运算符正确匹配。 看到这个最小的例子:

my.seq <- seq(0, 0.4, len = 5)
table(my.seq)                  # ok! returns  0 0.1 0.2 0.3 0.4 
                               #              1   1   1   1   1 

which(my.seq == 0.2)           # ok! returns  3
which(my.seq == 0.3)           # !!! returns  integer(0)

手动创建序列时,它似乎有效:

my.seq2 <- c(0.00, 0.10, 0.20, 0.30, 0.40)

which(my.seq2 == 0.3)           # ok! returns  4

你对此有任何解释吗?我使用which(round(my.seq, 2) == 0.3)解决了这个问题,但我会对导致问题的原因感兴趣。

提前感谢您的意见。

3 个答案:

答案 0 :(得分:3)

计算机只是不能很好地表示浮点数。电子表格隐藏这一点的一般趋势,作为大多数人处理计算机上的数字的主要方式,导致了许多问题。

永远不会与精确的浮点值匹配。 R中有一些功能可以解决这个问题(例如all.equal),但我更喜欢以下内容。

假设您有一个未知的浮点变量A,并且您想要查看它是否等于0.5。

abs(A - 0.5) < tol

将容差设置为0.5。例如,tol <- 0.0001可能适合您。

如果你的值看起来像是整数,那么它们应该是整数。或者,如果您知道要测试的小数级别,则可以舍入到该十进制级别。

答案 1 :(得分:2)

计算机很难存储确切的值。

> options(digits=22)
> seq(0, .4, len = 5)
[1] 0.0000000000000000000000 0.1000000000000000055511 0.2000000000000000111022
[4] 0.3000000000000000444089 0.4000000000000000222045
> .4
[1] 0.4000000000000000222045
> c(0, .1, .2, .3, .4)
[1] 0.0000000000000000000000 0.1000000000000000055511 0.2000000000000000111022
[4] 0.2999999999999999888978 0.4000000000000000222045

由于我们使用的是二进制浮点表示,因此我们无法准确表示感兴趣的值。它看起来因为.4的值略高于.4,.3的值比你输入.3本身的值稍微高一点。我相信其他人会为此提供一个更好的解释,但希望这可以解释这个问题。

答案 2 :(得分:2)

这是FAQ 7.31,它也提供了对问题进行更长时间讨论的链接。