R语言seq()函数生成序列时精度异常且表现不一致的原因咨询
R语言seq()函数生成序列时精度异常且表现不一致的原因咨询
这是一个典型的浮点数二进制表示精度限制问题,在所有遵循IEEE 754标准浮点数的编程语言中都可能遇到,R自然也不例外~
核心原因:十进制0.1无法用二进制精确表示
十进制的0.1转换成二进制是无限循环的小数(类似十进制里1/3 = 0.333...),计算机只能用一个近似值来存储它。当你用这个近似值作为步长累加生成序列时,微小的误差会逐步累积。有时候结果看起来“正常”,只是因为误差被R的默认打印精度掩盖了,并非真的没有误差。
结合你的代码实例分析
先看你提到的“正常”案例:
seq( from = -0.4, to = 0.4, by = 0.1 ) #> [1] -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4
这里看起来符合预期,是因为R默认只打印到小数点后1位左右,把底层的微小误差隐藏了。如果强制提高打印精度,你会发现这些值同样是近似值:
options(digits = 22) seq(from = -0.4, to = 0.4, by = 0.1) #> [1] -0.40000000000000002220446 -0.29999999999999998889777 -0.19999999999999998334665 #> [4] -0.09999999999999997779554 0.00000000000000000000000 0.10000000000000000555112 #> [7] 0.20000000000000001110223 0.30000000000000004440892 0.40000000000000002220446
而当你生成-0.3到0.3的序列时,误差累积的结果刚好没被默认打印精度掩盖。当你用options(scipen = 999)强制显示全部精度时,就看到了底层的近似存储值:
options(scipen = 999) seq( from = -0.3, to = 0.3, by = 0.1 ) #> [1] -0.29999999999999998889777 -0.19999999999999998334665 #> [3] -0.09999999999999997779554 0.00000000000000005551115 #> [5] 0.10000000000000003330669 0.20000000000000001110223 #> [7] 0.29999999999999998889777
两个范围表现不同,完全是误差累积的“巧合”:-0.4到0.4的序列累加次数更多,最终误差刚好在四舍五入后匹配预期的十进制值;而-0.3到0.3的序列误差累积结果刚好突破了默认打印的精度阈值。
解决办法
- 若仅需要符合预期的打印效果,可使用
round()函数将结果四舍五入到指定精度:round(seq(from = -0.3, to = 0.3, by = 0.1), 1) #> [1] -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 - 若需要精确的十进制运算,可借助R的
decimal或gmp包,用高精度十进制类型替代默认的二进制浮点数。
内容来源于stack exchange
相关产品推荐
相关产品推荐

