double findaroot(double x1, double x2){ //finds the root between two values
double gap = Math.abs(x1 - x2); //find the initial interval
while(gap > INTERVAL) { //check for precision
gap = gap / 2; //halve the interval
double x3 = x1 + gap;
if (f(x3) == 0) { //check for symmetry
return x3;
} else if (Math.signum(f(x1)) == Math.signum(f(x3))){
x1 = x3; //redefine the interval
} else {
x2 = x3; //redefine the interval
}
findaroot(x1, x2); //call again
}
return (x1 + x2) / 2; //return the mean
}
我试图在间隔(-143,0.222222)中找到f(x)= - 21x ^ 2 + 10x-1的解。指南声明我应该实现二分法来解决这个问题。目前,此方法适用于我必须通过的10个测试用例中的8个,但它为上述值提供了“超出时间限制”错误。在间隔之间给定精度水平至少为“0.000001”的情况下,近似根需要15秒。
我不确定如何在不改变方法的情况下提高效率。我已经实现了 Horner的方法来计算函数,因为Math.pow(x1, x2)
花了太长时间。
答案 0 :(得分:1)
只需删除第findaroot(x1, x2);
行即可。您还没有使用此递归函数调用的结果。
编辑:这是您的代码的递归版本(未经过测试)
double findaroot(double x1, double x2){ //finds the root between two values
double gap = Math.abs(x1 - x2); //find the initial interval
if (gap > INTERVAL) { //check for precision
gap = gap / 2; //halve the interval
double x3 = x1 + gap;
if (f(x3) == 0) { //check for symmetry
return x3;
} else if (Math.signum(f(x1)) == Math.signum(f(x3))){
x1 = x3; //redefine the interval
} else {
x2 = x3; //redefine the interval
}
return findaroot(x1, x2);
}
else
return (x1 + x2) / 2; //return the mean
}
答案 1 :(得分:0)
正如其他人已经说过的那样:findaroot的递归调用是错误的/不需要的。这段代码适合我:
private final int NMAX = 100;
public double solve(Function f, double a, double b, double tolerance) {
if (a >= b) throw new IllegalArgumentException("illegal interval!");
double fa = f.value(a);
if (Math.signum(fa) == Math.signum(f.value(b))) throw new IllegalArgumentException("solution not within interval!");
for (int n = 0; n < NMAX; n++) {
double c = (a + b) / 2;
double fc = f.value(c);
if ((fc == 0.0) || ((b - a) / 2 < tolerance)) {
// solution found
return c;
}
// adapt interval
if (Math.signum(fc) == Math.signum(fa)) {
a = c;
fa = fc;
} else {
b = c;
}
}
return Double.NaN;
}