问题
I'm attempting to write a program in C which finds the numeric value of the second derivative of f(x) where x is given. When I use my function to find the first derivative, everything seems to be working okay, but the recursive second derivative part always gives me 0.0. Here's my function:
double derivative(double (*f)(double), double x0, int order) {
if(order == 1){
const double delta = 1.0e-6;
double x1 = x0-delta;
double x2 = x0+delta;
double y1 = f(x1);
double y2 = f(x2);
return (y2 - y1) / (x2 - x1);
} else if(order == 2) {
const double delta = 1.0e-6;
double x1 = derivative(f, x0, 1)-delta;
double x2 = derivative(f, x0, 1)+delta;
double y1 = derivative(f, f(x1), 1)-delta;
double y2 = derivative(f, f(x2), 1)+delta;
return (y2 - y1) / (x2 - x1);
} else {
printf("order too high error \n");
return 0;
}
}
I understand why it doesn't work as intended -- here I attempt to find the second derivative of f by deriving based on the function f and the value of f'(x). But I've been working on this for hours, and I cannot come up with a proper algorithm to do this.
Any help would be very appreciated. Thanks in advance!
回答1:
I would implement it like this:
double derivative(double (*f)(double), double x0, int order)
{
const double delta = 1.0e-6;
double x1 = x0 - delta;
double x2 = x0 + delta;
if (order == 1) {
double y1 = f(x1);
double y2 = f(x2);
return (y2 - y1) / (x2 - x1);
} else {
double y1 = derivative(f, x1, order - 1);
double y2 = derivative(f, x2, order - 1);
return (y2 - y1) / (x2 - x1);
}
}
Because then there is no need for a "order too high error".
回答2:
I change your code into following code and it works as expected.
double derivative(double (*f)(double), double x0, int order)
{
const double delta = 1.0e-6;
if (order == 1) {
double x1 = x0 - delta;
double x2 = x0 + delta;
double y1 = f(x1);
double y2 = f(x2);
return (y2 - y1) / (x2 - x1);
} else if(order == 2) {
double x1 = x0 - delta;
double x2 = x0 + delta;
double y1 = derivative(f, x1, 1);
double y2 = derivative(f, x2, 1);
return (y2 - y1) / (x2 - x1);
} else {
printf("order too high error \n");
return 0;
}
}
回答3:
Parham Alvani has already answered your question and pointed out the logical error in your function. So this is not really an answer, just some additional remarks.
You can make the function entirely recursive without treating any case except the base case separately:
double derivative(double (*f)(double), double x, int order)
{
const double eps = 1.0e-3;
if (order == 0) return f(x);
double y1 = derivative(f, x - eps, order - 1);
double y2 = derivative(f, x + eps, order - 1);
return (y2 - y1) / (2 * eps);
}
For higher-order derivatives, you end up evaluating the same function values several times, however, so you could evaluate the derivatives recursively beforhand and hard-code the relations:
Δf(x) / Δx = (f(x + ε) - f(x - ε)) / (2·ε)
Δ²f(x) / Δx² = (f(x + 2·ε) - 2·f(x) + f(x - 2·ε)) / (4·ε²)
Δ³f(x) / Δx³ = (f(x + 3·ε) - 3·f(x + ε) + 3·f(x - ε) - f(x - 3·ε)) / (8·ε³)
and so on. For the higher-order derivatives, chosing the ε
value gets tricky, however. Chosing it too small will lead to errors when the difference between the evaluated function values is small.
来源:https://stackoverflow.com/questions/28317868/recursively-find-the-second-derivative