我偶然发现了像
这样的代码double x,y = ...;
double n = sqrt(x*x+y*y);
if (n > 0)
{
double d1 = (x*x)/n;
double d2 = (x*y)/n;
}
我想知道x
和y
的小值这样的表达式的数值稳定性。
对于这两个表达式lim (x->0, y->0) (...) = 0
,从数学的角度来看,它看起来很安全(分母O(x²)而分母是O(x))。
然而我的问题是:此代码是否存在任何数字问题?
编辑:如果可能的话,我想避免重写表达式,因为n
实际使用了两次以上以保持可读性(在上下文中相对清楚会发生什么)。
答案 0 :(得分:6)
如果x
和y
非常接近DBL_MIN
,则计算结果如下:
如果x
为DBL_MIN
,则可能出现下溢或极度精确损失
非常接近x * x
,例如0.0
可能是1E-300
* 1E-300
,或者。0.0
(对于稍微大一些的值),它可能会导致所谓的
逐渐下溢,极度精度损失:例如:同
IEEE双倍(大多数,如果不是全部台式机和笔记本电脑),x
将为y
。显然,如果两者都发生这种情况
* n == 0.0
和x
,即使y
和hypot
,您也会n
x * x
都是积极的。
在C ++ 11中,有一个函数0.0
,它将解决问题
d1
的问题;如果0.0
为(x / n) * x
,则0.0
仍然存在
是{{1}}; {{1}}你可能会得到更好的结果
(但我认为仍有可能存在极限情况
结束{{1}}或逐渐下溢 - 我没有充分分析它以确保)。更好的解决方案
将以不同方式扩展数据,以避免这种限制
案例。