我正在尝试编写一个程序,当给定一个函数和一个高值和低值时,它会找到高和低之间的零。我以二进制搜索方式递归地编写了它。当我运行JUnit测试时,它会给我一个堆栈溢出错误,除非我给它基本情况。这是我正在使用的代码。 功能代码:
public class Function implements FunctionInterface{
public static double f(double x){
return x*x-4;
}
}
查找零的代码:
public class NumericalAnalysis {
public double solveForZero(Function f, double low, double high) {
double h = high;
double l = low;
double mid = (h+l)/2;
double x = Function.f(mid);
if(x == 0.0) {
return mid;
}else if(x < 0.0){
l = mid;
return solveForZero(f, h, l);
}else if (x > 0.0){
h = mid;
return solveForZero(f, h, l);
}
return mid;
}
}
测试代码:
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.After;
import org.junit.AfterClass;
public class TestNumericalAnalysis{
private NumericalAnalysis myAnalyzer;
@Before
public void setUp(){
myAnalyzer = new NumericalAnalysis();
}
@Test
public void testSolveForZero(){
double ans = myAnalyzer.solveForZero(new Function(), 0.0, 100.0);
assertEquals(4.0, ans, 0.001);
}
}
我使用的函数是x * x-4,高是100.0,低是0.0。我的希望是,我错过了一些非常简单但没有看到它的东西。
答案 0 :(得分:2)
我看到三个问题。
在递归调用中,看起来l
和h
是向后的,所以你在错误的时间间隔内递归。因此,你永远找不到根,它会继续尝试,直到你的堆栈空间不足。
该算法假定在给定的时间间隔内被测试的函数是“向上和向右”。如果您的函数在范围内减小(例如F(x) = -x
),则无效。这就是为什么Newton-Raphson iteration,这个算法稍微复杂一点,需要函数的导数。
最后,大家都在评论中看到了这一点:浮点表示通常是近似值。 x
正好为0的f(x)
可能无法准确表示。在这种情况下,低,高和中可能都会收敛到非常接近期望值的值,但结果将不会精确为0,因此它将继续递归而不会取得更多进展。这通常通过测试小范围和/或在间隔非常小时停止递归来处理。