XTS中的Decimal值为何不相等?如何正确进行比较?
解决XTS对象中Decimal值比较的精度问题
我来帮你捋清楚这个问题——其实这不是XTS的特性,核心原因是浮点数(哪怕你用了Decimal类型)的精度存储问题,尤其是像1.9这种无法用二进制浮点数精确表示的数值。
问题根源
你觉得1.9×3=5.7完全没有舍入误差,但实际在计算机里:
- 1.9这个数本身,在默认的二进制浮点数(比如R里的
numeric类型)中是无法精确存储的,它会被存成一个极其接近1.9的近似值。 - 当你把这个近似值乘以3之后,得到的结果会接近5.7,但和你手动输入的
5.7(同样是一个近似值)并不完全相等,这时候直接用==比较自然会失败。 - 整数能正常比较,是因为整数可以被二进制浮点数精确存储,不存在近似问题。
正确的比较方法
这里给你几个实用的解决方案:
1. 用近似比较代替精确相等
永远不要直接用==比较浮点数(包括Decimal类型),改用R内置的all.equal()函数,它会自动处理合理的精度差异:
library(xts) # 假设你的XTS对象是这样创建的(以decimal包为例) library(decimal) t <- xts(x = decimal(c(1.9)), order.by = as.Date("2018-01-03")) # 用all.equal进行近似比较 all.equal(t["2018-01-03"], decimal(5.7)) # 如果是默认numeric类型,可以自定义容忍度(比如1e-10) all.equal(t["2018-01-03"], 5.7, tolerance = 1e-10)
all.equal()会返回TRUE如果两个值在合理的精度范围内匹配,默认的容忍度已经能覆盖绝大多数日常场景。
2. 确保Decimal类型被正确保留
如果你确实想用Decimal类型做精确比较,先检查XTS对象有没有偷偷把类型转成了numeric:
# 检查列的类型 class(t[,1])
如果输出是numeric而不是decimal,说明XTS在创建时自动转换了类型(XTS对非numeric类型的支持有限)。这种情况下,要么改用tibble/data.table结合日期索引来维护Decimal类型,要么还是回到近似比较的方案更省心。
3. 用Decimal运算生成预期值
不要手动输入5.7,而是用原始的Decimal值计算预期结果,这样能保证两边的精度一致:
# 用Decimal运算生成预期值 expected_value <- decimal(1.9) * 3 # 再进行比较 all.equal(t["2018-01-03"], expected_value)
这种方式能避免手动输入带来的二次精度误差,比较结果会更可靠。
内容的提问来源于stack exchange,提问作者user6467981
相关产品推荐
相关产品推荐

