递归期间的堆栈溢出

时间:2017-09-14 19:27:45

标签: java recursion junit stack-overflow

我正在尝试编写一个程序,当给定一个函数和一个高值和低值时,它会找到高和低之间的零。我以二进制搜索方式递归地编写了它。当我运行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。我的希望是,我错过了一些非常简单但没有看到它的东西。

1 个答案:

答案 0 :(得分:2)

我看到三个问题。

  1. 在递归调用中,看起来lh是向后的,所以你在错误的时间间隔内递归。因此,你永远找不到根,它会继续尝试,直到你的堆栈空间不足。

  2. 该算法假定在给定的时间间隔内被测试的函数是“向上和向右”。如果您的函数在范围内减小(例如F(x) = -x),则无效。这就是为什么Newton-Raphson iteration,这个算法稍微复杂一点,需要函数的导数。

  3. 最后,大家都在评论中看到了这一点:浮点表示通常是近似值。 x正好为0的f(x)可能无法准确表示。在这种情况下,低,高和中可能都会收敛到非常接近期望值的值,但结果将不会精确为0,因此它将继续递归而不会取得更多进展。这通常通过测试小范围和/或在间隔非常小时停止递归来处理。