R语言中%in%运算符为何出现异常匹配行为?
问题原因:浮点数精度误差
这是典型的浮点数二进制存储精度问题,和R的seq()函数计算逻辑直接相关:
先看
seq(-1, 0, 0.1)的实际生成值
打印序列并显示足够多的小数位,你会发现序列里看似是-0.1的元素,实际存储的是一个接近但不等于精确-0.1的数值:seq1 <- seq(-1, 0, 0.1) print(seq1, digits = 16) # 输出的倒数第二个值会是类似 -0.1000000000000001 的近似值原因是
0.1在二进制中是无限循环小数,无法被精确存储。seq()每次累加这个不精确的0.1,多次累加后误差被放大,最终得到的“-0.1”和你直接输入的-0.1并非同一个浮点数。%in%的判断逻辑%in%本质是对每个元素执行==精确比较。当你用(-0.1) %in% seq1时,是拿精确的-0.1和序列里带精度误差的近似值对比,自然返回FALSE;而c(-0.2, -0.1)里的-0.1是你直接输入的,和用来比较的-0.1是同一个浮点数,所以==比较返回TRUE,%in%结果也就为TRUE。
解决方法
- 方法一:用整数生成序列再缩放,避免浮点数累加误差:
seq1 <- seq(-10, 0, 1) / 10 (-0.1) %in% seq1 # 返回 TRUE - 方法二:用近似相等判断代替精确比较,比如
all.equal()或dplyr::near():any(sapply(seq1, function(x) all.equal(x, -0.1))) # 返回 TRUE # 或者使用dplyr的near函数 library(dplyr) any(near(seq1, -0.1)) # 返回 TRUE
内容的提问来源于stack exchange,提问作者Guillem Pocull
相关产品推荐
相关产品推荐

