首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >sqrt(x+a) - sqrt(x)的数值稳定计算

sqrt(x+a) - sqrt(x)的数值稳定计算
EN

Stack Overflow用户
提问于 2015-09-07 19:13:57
回答 1查看 1.3K关注 0票数 9

对于全参数范围x,一个>= 0,有一种优雅的数值稳定计算方法吗?

代码语言:javascript
复制
f(x,a) = sqrt(x+a) - sqrt(x)

此外,是否有任何编程语言或库提供这种功能?如果是的话,用什么名字?我现在没有使用上述表达方式的具体问题,但在过去遇到过很多次,而且一直认为这个问题以前一定已经解决了!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-07 19:19:34

是的,有!如果xa中至少有一个是正的,则可以使用:

代码语言:javascript
复制
f(x, a) = a / (sqrt(x + a) + sqrt(x))

它在数值上是完全稳定的,但它本身几乎不值得一个库函数。当然,当x = a = 0时,结果应该是0

说明:sqrt(x + a) - sqrt(x)等于(sqrt(x + a) - sqrt(x)) * (sqrt(x + a) + sqrt(x)) / (sqrt(x + a) + sqrt(x))。现在将前两个项乘以得到sqrt(x+a)^2 - sqrt(x)^2,这将简化为a

这里有一个演示稳定性的示例:对于原始表达式来说,麻烦的情况是x + ax在值上非常接近(或者当a的大小比x小得多时)。例如,如果x = 1a是小的,我们从1周围的泰勒展开式中知道sqrt(1 + a)应该是1 + a/2 - a^2/8 + O(a^3),所以sqrt(1 + a) - sqrt(1)应该接近a/2 - a^2/8。让我们为一个特定的小a选择尝试一下。下面是原始函数(在本例中是用Python编写的,但您可以将其视为伪代码):

代码语言:javascript
复制
def f(x, a):
    return sqrt(x + a) - sqrt(x)

这是稳定的版本:

代码语言:javascript
复制
def g(x, a):
    if a == 0:
        return 0.0
    else:
        return a / ((sqrt(x + a) + sqrt(x))

现在让我们看看x = 1a = 2e-10能得到什么

代码语言:javascript
复制
>>> a = 2e-10
>>> f(1, a)
1.000000082740371e-10
>>> g(1, a)
9.999999999500001e-11

我们应该得到的值是(直到机器精度):a/2 - a^2/8 -对于这个特定的a,立方和高阶项在IEEE 754双精度浮动环境中是微不足道的,它只提供大约16位十进制的精度。让我们计算这个值以进行比较:

代码语言:javascript
复制
>>> a/2 - a**2/8
9.999999999500001e-11
票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32444817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档