【问题标题】:Stack Overflow during Recursion递归期间的堆栈溢出
【发布时间】:2017-10-03 16:45:15
【问题描述】:

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

【问题讨论】:

  • 欢迎来到 StackOverflow。请阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。具体来说,您给定的代码仅定义了一个函数并退出。发布一个 full MCVE,并坚持几个调试 print 语句。
  • 编辑提供所有代码
  • 浮点数并不精确,在大多数情况下,您不会以这种方式找到零 - 最好让它找到“足够接近零”的东西。
  • 换句话说:x == 0 永远不会满足。另见stackoverflow.com/questions/1088216/…

标签: java recursion junit stack-overflow


【解决方案1】:

我看到了三个问题。

  1. 在递归调用中,lh 看起来是倒退的,所以你在错误的间隔上递归。因此你永远找不到根,它会一直尝试直到你用完堆栈空间。

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

  3. 最后,每个人都在 cmets 中看到:浮点表示通常是近似值。 f(x) 恰好为 0 的 x 可能无法精确表示。在这种情况下,low、high 和 mid 可能都收敛在一个非常接近期望值的值上,但结果不会完全为 0,因此它会继续递归而不会取得更多进展。这通常通过测试小范围和/或在间隔非常小时停止递归来处理。

【讨论】:

    猜你喜欢
    • 2020-09-23
    • 2015-02-08
    • 2020-12-17
    • 1970-01-01
    • 2015-04-04
    • 2017-01-20
    • 2018-12-02
    • 2017-09-06
    • 2019-07-08
    相关资源
    最近更新 更多