如何避免由于舍入错误导致的 NaN
how to avoid NaNs due to rounding errors
考虑计算
x * -3/10 + sqrt(1/20 - x^2 / 100)
当 x=sqrt(5)
。由于舍入误差,sqrt 参数变为负数,整个表达式的结果为 NaN
.
> x <- sqrt(5)
> x * -3/10 + sqrt(1/20 - x^2 / 100)
[1] NaN
Warning message:
In sqrt(1/20 - sqrt(5)^2/100) : NaNs produced
正确的结果是
> sqrt(5) * -3/10
[1] -0.6708204
如果您不希望平方根为 return NaN
值,一种选择是仅使用 pmax
以确保其参数至少为 0:
x * -3/10 + sqrt(pmax(0, 1/20 - x^2 / 100))
# [1] -0.6708204
如果你想要 return NaN
当 sqrt
的参数非常负但 0 当它真的接近 0 但负时,那么 ifelse
可以帮助:
x <- sqrt(4:6)
special.sqrt <- function(x) ifelse(x < -1e-10, NaN, sqrt(pmax(0, x)))
x * -3/10 + special.sqrt(1/20 - x^2 / 100)
# [1] -0.5000000 -0.6708204 NaN
考虑计算
x * -3/10 + sqrt(1/20 - x^2 / 100)
当 x=sqrt(5)
。由于舍入误差,sqrt 参数变为负数,整个表达式的结果为 NaN
.
> x <- sqrt(5)
> x * -3/10 + sqrt(1/20 - x^2 / 100)
[1] NaN
Warning message:
In sqrt(1/20 - sqrt(5)^2/100) : NaNs produced
正确的结果是
> sqrt(5) * -3/10
[1] -0.6708204
如果您不希望平方根为 return NaN
值,一种选择是仅使用 pmax
以确保其参数至少为 0:
x * -3/10 + sqrt(pmax(0, 1/20 - x^2 / 100))
# [1] -0.6708204
如果你想要 return NaN
当 sqrt
的参数非常负但 0 当它真的接近 0 但负时,那么 ifelse
可以帮助:
x <- sqrt(4:6)
special.sqrt <- function(x) ifelse(x < -1e-10, NaN, sqrt(pmax(0, x)))
x * -3/10 + special.sqrt(1/20 - x^2 / 100)
# [1] -0.5000000 -0.6708204 NaN