2
double MyClass::dx = ?????;

double MyClass::f(double x)
{
    return 3.0*x*x*x - 2.0*x*x + x - 5.0;
}

double MyClass::fp(double x)    // derivative of f(x), that is f'(x)
{
    return (f(x + dx) - f(x)) / dx;
}

使用有限差分法进行推导时,选择最佳dx值至关重要。在数学上,dx必须尽可能小。但是,我不确定选择最小的正双精度数(即 2.2250738585072014 x 10 -308)是否是正确的选择。

是否有最佳数值区间或精确值可供选择dx以使计算误差尽可能小?

(我使用的是 64 位编译器。我将在 Intel i5 处理器上运行我的程序。)

4

2 回答 2

3

选择最小的可能值几乎肯定是错误的:如果dx是那个最小的数字,那么由于四舍五入f(x + dx)完全等于。f(x)

所以你有一个权衡:选择dx太小,你会因为舍入误差而失去精度。选择太大,由于x变化时导数的变化,您的结果将不精确。

要判断数字错误,请在数学上考虑(f(x + dx) - f(x))/f(x)1。分子表示您要计算的差异,但分母表示您正在处理的数字的大小。如果该分数约为 2 ‒<i>k,那么您可以预期结果中的精度约为k位。

如果你知道你的函数,你可以计算出选择dx太大会导致什么错误。然后,您可以平衡事物,以便由此产生的误差与舍入产生的误差大致相同。但是,如果您知道该函数,则最好提供一个直接计算导数的函数,例如您的示例中的 polygonal f

pogorskiy指出Wikipedia 部分建议了 sqrt(ε) x的值,或近似。如果没有关于函数的任何更详细的知识,这样的经验法则将提供一个合理的默认值。另请注意,同一部分建议不要除以,而是除以,因为这会将计算产生的舍入误差考虑在内。但我想整篇文章都充满了您可能会使用的建议。1.5e-8 * xdx(x + dx) - xx + dx


1这个公式确实应该除以f(x),而不是除以dx,即使过去的编辑想法不同。我试图比较除法后剩余的有效位数,而不是切线的斜率。

于 2012-11-17T11:58:17.373 回答
-2

为什么不直接使用幂律推导导数,你会得到一个准确的答案:

f(x) = 3x^3 - 2x^2 + x - 5
f'(x) = 9x^2 - 4x + 1

所以:

f(x) = 3.0 * x * x * x - 2.0 * x * x + x - 5.0
fp(x) = 9.0 * x * x - 4.0 * x + 1.0
于 2012-11-17T14:30:54.987 回答