我正在尝试用C编写一个程序,它找到f(x)的二阶导数的数值,其中给出了x。当我使用我的函数找到一阶导数时,一切似乎都运行正常,但递归的二阶导数部分总是给我0.0。这是我的功能:
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;
}
}
我理解为什么它不能按预期工作 - 在这里我试图通过基于函数f和f'(x)的值导出来找到f的二阶导数。但是我已经在这个问题上工作了好几个小时,我无法想出一个合适的算法来做到这一点。
非常感谢任何帮助。提前谢谢!
答案 0 :(得分:5)
我将您的代码更改为以下代码,并且按预期工作。
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;
}
}
答案 1 :(得分:2)
我会像这样实现它:
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);
}
}
因为那时不需要“订单太高错误”。
答案 2 :(得分:1)
Parham Alvani已经回答了你的问题并指出了你的功能中的逻辑错误。所以这不是一个真正的答案,只是一些额外的评论。
你可以使函数完全递归,而不必处理除基本情况之外的任何情况:
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);
}
对于高阶导数,你最终会多次评估相同的函数值,所以你可以递归地评估导数,并对关系进行硬编码:
Δ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·ε³)
等等。然而,对于高阶导数,选择ε
值会变得棘手。当评估的函数值之间的差异很小时,选择它太小会导致错误。