R语言使用浮点数值进行条件过滤时的布尔判断异常问题
问题根本原因
你遇到的所有异常都是二进制浮点数存储精度问题导致的:
- 0.1这类十进制小数无法被二进制浮点数精确表示,你用
seq(-1,1,0.1)生成的数值本质上都带有微小的尾数位误差,不是你以为的刚好0.1、0.9 - 打印时R默认只显示有限小数位,会把微小误差隐藏,看起来是1.0的数值实际计算时可能是略大于1的数值,所以
<=1返回FALSE,等于0.1的匹配也找不到对应行
验证方法
运行以下代码可以直观看到误差:
# 查看0.1的实际存储值,保留20位小数 sprintf("%.20f", 0.1) # 查看你生成的序列中对应0.1位置的实际值 sprintf("%.20f", input_vector_full[input_vector_full > 0.09 & input_vector_full < 0.11]) # 查看0.1+0.9的实际计算结果 sprintf("%.20f", 0.1 + 0.9)
输出会看到0.1实际存储为类似0.10000000000000000555的数值,0.9也存在微小误差,二者相加的结果略大于1,因此布尔判断返回FALSE。
解决方案
- 条件判断时不要直接用
==或者无容差的大小比较,要引入可接受的误差范围:- 判断相等用
all.equal()函数,或者手动加容差:abs(x - 0.1) < 1e-9 - 原布尔标志判断修改为:
df2$bool_flag <- df2$sum_absolute <= 1 + 1e-9 - dplyr筛选修改为:
df2 %>% filter(abs(x - 0.1) < 1e-9)
- 判断相等用
- 生成步长为0.1的序列时,更稳妥的写法是先生成整数再除以10,避免seq的步长累加误差:
input_vector_full <- seq(-10,10,1)/10,这种方式生成的数值精度误差会大幅降低。
内容的提问来源于stack exchange,提问作者Jamalan
相关产品推荐
相关产品推荐

