分裂表达式的数值稳定性

时间:2014-02-20 09:28:56

标签: c++ numeric

我偶然发现了像

这样的代码
double x,y = ...;
double n = sqrt(x*x+y*y);
if (n > 0)
{
   double d1 = (x*x)/n;
   double d2 = (x*y)/n;
}

我想知道xy的小值这样的表达式的数值稳定性。

对于这两个表达式lim (x->0, y->0) (...) = 0,从数学的角度来看,它看起来很安全(分母O(x²)而分母是O(x))。

然而我的问题是:此代码是否存在任何数字问题?

编辑:如果可能的话,我想避免重写表达式,因为n实际使用了两次以上以保持可读性(在上下文中相对清楚会发生什么)。

1 个答案:

答案 0 :(得分:6)

如果xy非常接近DBL_MIN,则计算结果如下: 如果xDBL_MIN,则可能出现下溢或极度精确损失 非常接近x * x,例如0.0可能是1E-300 * 1E-300,或者。0.0 (对于稍微大一些的值),它可能会导致所谓的 逐渐下溢,极度精度损失:例如:同 IEEE双倍(大多数,如果不是全部台式机和笔记本电脑),x将为y。显然,如果两者都发生这种情况 * n == 0.0x,即使yhypot,您也会n x * x都是积极的。

在C ++ 11中,有一个函数0.0,它将解决问题 d1的问题;如果0.0(x / n) * x,则0.0仍然存在 是{{1}}; {{1}}你可能会得到更好的结果 (但我认为仍有可能存在极限情况 结束{{1}}或逐渐下溢 - 我没有充分分析它以确保)。更好的解决方案 将以不同方式扩展数据,以避免这种限制 案例。