四舍五入问题

标签 r

我正在阅读The R Inferno,并且遇到了我不了解的内容。除了Inferno中的8.2.23节,在比较浮点数方面还有一些很好的问题:question1question2

但是,使用all.equal仍然遇到问题。使用默认的all.equal我得到了预期的结果(大部分是)。

> all.equal(2,1.99999997)
[1] "Mean relative difference: 1.5e-08"
> all.equal(2,1.99999998) #I expected FALSE here
[1] TRUE
> all.equal(2,1.99999999)
[1] TRUE

我不确定为什么在1.99999998中该函数返回TRUE,但这与我指定公差级别的以下行为无关:
> all.equal(2,1.98,tolerance=0.01) #Behaves as expected
[1] "Mean relative difference: 0.01"
> all.equal(2,1.981,tolerance=0.01) #Does not behave as expected
[1] TRUE

此外,
> all.equal(2,1.980000000001,tolerance=0.01)
[1] TRUE 

但是,如果我们计算:
> diff(c(1.981,2))
[1] 0.019

显然,
> diff(c(1.981,2)) >= 0.01
[1] TRUE

那么,为什么all.equal不能以容差0.01区分2和1.981?

编辑

从文档中:比例= NULL(默认值)的数值比较是通过首先计算两个数值向量的平均绝对差来完成的。如果此值小于公差或不是有限的,则使用绝对差,否则使用平均绝对差来缩放相对差。

在这里我不了解行为。我可以看到diff(1.981,2)不是有限的:
> sprintf("%.25f",diff(c(1.981,2)))
[1] "0.0189999999999999058530875"

但是,然后按比例缩放呢?当每个向量的长度为1时,平均绝对差应等于两个数字的差,并且除以平均绝对差将得出1。显然,我理解这里的逻辑是错误的。

最佳答案

这与浮点精度有关。乍一看,手册并不完全清楚,但是在您的示例中,mean absolute difference2-1.9810.019,即> 0.01,即tolerancescale也是NULL。因此,进行的比较是通过平均绝对差缩放的相对差。嗯?

使用tolerance意味着您关心所涉及数字的大小。 Relative difference并不考虑差异(绝对值)有多大,而是相对于要比较的数字有多大。给定链接中的示例,与1,000,000,0001,000,000,001之间的区别(在5和6之间)的区别更大(我使用的术语是宽松的)。

因此,如果两个数字之间的相对差异小于tolerance,则认为这些数字相等。对于两个单个数字(如本例所示),相对差由下式给出:

( current - target ) / current

哪一个
( 2 - 1.981 ) / 2 == 0.0095

您指定的公差为0.01,因此数字被视为相等,因为相对差小于此值。这些数字之间的差异±的相对差异也恰好是最小的可表示浮点数!
identical( abs( ( 2 - 0.0095 ) - ( 1.981 + 0.0095 ) ) , .Machine$double.eps )
[1] TRUE

现在尝试:
all.equal( 2 , 1.981 , 0.00949999999999 )
[1] "Mean relative difference: 0.0095"

关于四舍五入问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18794129/

相关文章:

用开头的模式替换字符串末尾的模式

r - 使用日期时间POSIXlt创建R data.table时出错

performance - 提高性能/速度

r - highcharter 中是否有相当于 geom_ribbon 的东西?

使用 ggcorrplot2 : "x-axis" labels get cropped 的 R 相关图

r - 使用 R 中预先存在的名称系统地重命名列名称

r - 将 fusionMatrix 的输出保存为 .csv 表

r - 在我自己的函数中使用 summarise_ 和 group_by_

r - 基于共享标识符将两个数据帧的值相乘

r - 当下载按钮在 R 服务器中运行时显示 "Loading",并在完成任务时显示隐藏消息