具有相同输入的相同函数 returns 个不同的值

Same function with same inputs returns different values

假设我有如下函数:

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

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

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

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

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

请参阅评论中有关浮点数学的链接。处理方法如下:

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>