具有相同输入的相同函数 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>
假设我有如下函数:
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>