1

可以说我有一个如下功能:

testFunction <- function(testInputs){
    print( sum(testInputs)+1 == 2 )
    return( sum(testInputs) == 1 )
}

当我在命令行上使用以下输入进行测试时:c(0.65, 0.3, 0.05),它会按预期打印并返回 TRUE。

但是,当我使用 c(1-0.3-0.05, 0.3, 0.05) 时,我会打印 TRUE 并返回 FALSE。这没有任何意义,因为它意味着 sum(testInputs)+1 是 2 但 sum(testInputs) 不是 1。

这就是我的想法:不知何故,打印值不完全是 1,但可能是 0.9999999...,并且它在显示器上四舍五入。但这只是一个猜测。这究竟是如何工作的?

4

1 回答 1

1

这完全是一个浮点问题,但对我来说有趣的是它如何证明 的返回值sum()会产生这个错误,但+你却不明白。

请参阅评论中有关浮点数学的链接。以下是如何处理它:

sum(1-0.3-0.5, 0.3, 0.05) == 1
# [1] FALSE
dplyr::near(sum(1-0.3-0.05, 0.3, 0.05), 1)
# [1] TRUE

对我来说,最吸引人的是:

(1 - 0.3 - 0.05 + 0.3 + 0.05) == 1
# [1] TRUE

因为您无法预测浮点运算的各种实现将如何表现,所以您需要对其进行更正。在这里,不要使用 ,而是==使用dplyr::near()。这个问题(浮点数学是不精确的,也是不可预测的),存在于各种语言中。一种语言中的不同实现将导致不同的浮点错误。

正如我在对另一个浮点问题的答案中所讨论的dplyr::near()那样all.equal(),这里有一个容差参数tol。默认情况下,它设置为.Machine$double.eps^0.5.Machine$double.eps是您的机器可以添加1并能够将其与 区分开来的最小数字1。这并不准确,但在那个数量级上。取平方根会使它比这大一点,并允许您准确识别那些偏离量的值,这些值会使相等的失败测试很可能是一个浮点错误。

注意:是的,near()在 dplyr 中,我几乎总是加载它,所以我忘了它不在 base 中……你可以使用all.equal(),但请查看near(). 这正是您需要的,没有您不需要的:

near
# function (x, y, tol = .Machine$double.eps^0.5) 
# {
#     abs(x - y) < tol
# }
# <environment: namespace:dplyr>
于 2018-03-18T23:23:40.263 回答