在C / C ++中实现派生

时间:2009-10-13 11:40:36

标签: c++ c algorithm math numerical-methods

f(x)的导数通常以编程方式计算以确保最大准确度?

我正在实现Newton-Raphson方法,它需要获取函数的导数。

8 个答案:

答案 0 :(得分:59)

我同意@erikkallen (f(x + h) - f(x - h)) / 2 * h是数值近似衍生物的通常方法。但是,获得正确的步长h有点微妙。

f(x + h) - f(x - h)) / 2 * h中的近似误差会随着h变小而减小,这表示您应该尽量减少h。但随着h变小,错误从浮点减法增加,因为分子需要减去几乎相等的数字。如果h太小,你可以在减法中失去很多精度。所以在实践中你必须选择一个不太小的值h最小化近似错误和数字错误的组合。

根据经验,您可以尝试h = SQRT(DBL_EPSILON)其中DBL_EPSILON是最小的双精度数e,使机器精度为1 + e != 1DBL_EPSILON约为10^-15,因此您可以使用h = 10^-710^-8

有关详细信息,请参阅这些notes选择微分方程的步长。

答案 1 :(得分:10)

Newton_Raphson假设你可以有两个函数f(x)及其导数f'(x)。如果您没有将衍生函数作为函数使用并且必须估计原始函数的导数,那么您应该使用另一个根查找算法。

Wikipedia root finding提供了一些建议,就像任何数值分析文本一样。

答案 2 :(得分:9)

alt text

alt text

1)第一种情况:

alt text

alt text - 相对舍入误差,double为2 ^ { - 16},float为2 ^ { - 7}。

我们可以计算总误差:

alt text

假设您正在使用双浮动操作。因此, h 的最佳值是2sqrt(DBL_EPSILON / f''(x))。你不知道 f''(x)。但你必须估计这个值。例如,如果 f''(x)约为1,则 h 的最佳值为2 ^ { - 7},但如果 f''(x )约为10 ^ 6,那么 h 的最佳值是2 ^ { - 10}!

2)第二种情况:

alt text

请注意,第二个近似误差比第一个更快。 但如果f'''(x)非常滞后,那么第一个选项更为可取:

alt text

注意,在第一种情况下,h与e成比例,但在第二种情况下,h与e ^ {1/3}成比例。对于双浮动操作,e ^ {1/3}是2 ^ { - 5}或2 ^ { - 6}。 (我想f'''(x)约为1)。


哪种方式更好?如果您不知道f''(x)和f'''(x),或者您无法估算这些值,则表示未知。据信第二种选择是优选的。但如果你知道f'''(x)非常大,请先使用。

h的最佳值是什么?假设f''(x)和f'''(x)约为1.还假设我们使用双浮点运算。然后在第一种情况下,h约为2 ^ { - 8},在第一种情况下,h约为2 ^ { - 5}。如果您知道f''(x)或f'''(x),请更正此值。

答案 3 :(得分:5)

fprime(x) = (f(x+dx) - f(x-dx)) / (2*dx)

对于一些小dx。

答案 4 :(得分:5)

你对f(x)有什么了解?如果你只有f作为黑盒子,你唯一能做的就是数字逼近导数。但准确性通常不太好。

如果您可以触摸计算f的代码,则可以更好地 。试试"automatic differentiation"。有一些很好的库可用。通过一些库魔法,您可以轻松地将您的功能转换为自动计算衍生物的功能。有关简单的C ++示例,请参阅source code in this德语讨论。

答案 5 :(得分:4)

你肯定想考虑约翰库克关于选择h的建议,但你通常不希望使用居中差异来近似导数。主要原因是,如果使用前向差异,即

,则需要额外的功能评估
f'(x) = (f(x+h) - f(x))/h

然后你将获得免费的f(x)值,因为你需要为牛顿方法计算它。当你有一个标量方程时,这不是什么大问题,但如果x是一个向量,那么f'(x)就是一个矩阵(Jacobian),你需要进行额外的函数评估来近似它使用中心差异方法。

答案 6 :(得分:3)

除了John D. Cooks的回答之外,重要的是不仅要考虑浮点精度,还要考虑函数f(x)的鲁棒性。例如,在金融领域,f(x)实际上是蒙特卡罗模拟并且f(x)的值具有一些噪声是常见的情况。在这些情况下,使用非常小的步长会严重降低导数的准确性。

答案 7 :(得分:1)

通常,信号噪声会影响衍生品质,而不是其他任何因素。如果你的f(x)中确实存在噪声,那么Savtizky-Golay是一种出色的平滑算法,通常用于计算良好的导数。简而言之,SG将多项式局部拟合到数据中,然后这个多项式可用于计算导数。