【问题标题】:Mysterious behaviour of seq and == operator. A precision issue?seq 和 == 运算符的神秘行为。精度问题?
【发布时间】:2012-07-31 14:35:20
【问题描述】:

我遇到了函数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) 解决了这个问题,但我会对导致问题的原因感兴趣。

提前感谢您的 cmets。

【问题讨论】:

  • 查看?'=='的文档,尤其是标题为“注意”的部分。
  • 谢谢。我只是不知道在这个简单的情况下可能会有任何问题,但是seq 做了一些计算,所以有。好吧,下次我肯定会更加小心使用round? (我的意思是对序列应用isTRUE(all.equal(x, 0.3)) 会有点矫枉过正,不是吗?:))
  • 它是否矫枉过正取决于您的代码中有多少错误。

标签: r precision seq


【解决方案1】:

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

从不匹配精确的浮点值。 R 中有一些函数可以处理这个问题(例如all.equal),但我更喜欢以下函数。

假设你有一个未知的浮点变量 A,你想看看它是否等于 0.5。

abs(A - 0.5) < tol

将公差设置为您需要的接近程度为 0.5。例如,tol &lt;- 0.0001 可能适合您。

如果您的值看起来应该是整数,则只是四舍五入。或者,如果您知道要测试的十进制级别,则可以四舍五入到该十进制级别。

【讨论】:

  • 谢谢。既然我知道了这个问题,我想我会听从你的建议的。
  • all.equal 使用的默认容差是sqrt(.Machine$double.eps),或1.490116e-08。因此,要复制all.equal 的结果,您可以使用@John 的方法并将其作为容差。
【解决方案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 的值高一点。我相信其他人会对此提供更好的解释,但希望这能对这个问题有所了解。

【讨论】:

  • 是的,确实如此。谢谢。我怀疑是这样的问题。那你有什么建议?从不匹配精确值,总是在比较之前四舍五入?
  • 不要自己进行四舍五入。查看 joran 的评论指向您的内容。我相信这会在某个时候将您带到all.equal
  • 它是。但在这个简单的情况下,我认为,我会坚持使用圆形,或者按照约翰(上图)的建议,以一定的宽容度来做。
【解决方案3】:

这里是FAQ 7.31,它还有一个链接,可以对这个问题进行更长的讨论。

【讨论】:

猜你喜欢
  • 2019-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
相关资源
最近更新 更多