r - R 中分数函数的数值爆炸问题

标签 r methods numeric numerical-methods

再见,

我正在 R 中使用这个函数:

betaFun = function(x){
  if(x == 0){
    return(0.5)
  }
  return( ( 1+exp(x)*(x-1) )/( x*(exp(x)-1) ) )
}

该函数对于每个 x 都是平滑且定义良好的(至少从理论角度来看),并且在 0 中极限接近 0.5(您可以通过使用霍皮塔定理来说服自己这一点)。

我有以下问题: enter image description here

即事实上,由于限制,R 错误地计算了值,并且我得到了 0 的爆炸。

这里我报告数字问题:

x = c(1e-4, 1e-6, 1e-8, 1e-10, 1e-12, 1e-13)  
sapply(x, betaFun)

[1] 5.000083e-01 5.000442e-01 2.220446e+00 0.000000e+00 0.000000e+00 1.111111e+10

正如你所看到的,评估非常奇怪,尤其是最后一个。 我以为我可以通过将缺失值定义为 0 来解决这个问题(正如您从代码中看到的那样),但事实并非如此。

Do you know how can I solve this numerical blow up problem?

我需要这个函数的高精度,因为我必须将其反转到 0 左右。我将使用 nleqslv 库中的 nleqslv 函数来实现。当然,如果函数存在数值问题,反演会返回错误的解。

最佳答案

我认为你在 x 接近 0 时评估 exp(x)-1 时失去了准确性。在 C 中,如果我将你的函数评估为

double  f2( double x)
{   return (x==0)   ? 0.5
            : (x*exp(x) - expm1(x))/( x*expm1(x));
}

问题就消失了。这里 expm1 是一个数学库函数,用于计算 exp(x) - 1,并且不会损失小 x 的精度。恐怕我不知道 R 是否有这个,但你希望它有。

不过,我认为您最好测试 |x|足够小,而不是 0.0。要点是,对于足够小的 x,x*exp(x) 和 expm1(x) 都将是 double x,因此它们的差值为 0。为了保持最大精度,可能需要在 0.5 的基础上添加一个线性项返回。我还没有准确地计算出“足够小”应该是多少,但我认为大约在 1e-16 左右。

关于r - R 中分数函数的数值爆炸问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54592139/

相关文章:

Java:setRequestMethod 不起作用

java - 在Java中如何用字符串替换任意字符?

c# - byte[] 到无符号 BigInteger?

r - knitr:如何在图中设置 keepaspectratio

c# - 如果抛出异常,则重复方法或函数 1 次或多次

vb.net - 数字类型的通用方法

python - 如何优化这个 NumPy 代码?

r - R 中的卡方检验是否有成对事后比较?

r - 获取一个向量在另一个向量中的值的索引?

r - 找出一个数字在给定范围内排名第几的百分位?