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が指摘したウィキペディアのセクションでは、sqrt(ε) xの値、つまり約が示唆されています。関数に関する詳細な知識がなくても、このような経験則によって適切なデフォルトが提供されます。また、同じセクションでは、 で割るのではなく、 で割ることが提案されていることに注意してください。これは、計算によって発生する丸め誤差が考慮されるためです。しかし、その記事全体が、あなたが使用できる提案でいっぱいだと思います.1.5e-8 * xdx(x + dx) - xx + dx


1f(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 に答える