【问题标题】:How to roll back on a recursive function that returns specific values如何回滚返回特定值的递归函数
【发布时间】:2014-11-15 10:54:52
【问题描述】:

您好,感谢您的时间和支持。

我的一般性问题是:如何在必须返回特定值的递归函数中回滚?

我的具体情况:

在这个问题中,我必须检查一个给定的多项式在给定的区间内是否有根,由它的边距定义:x1 和 x2。

我必须通过将区间 [x1,x2] 连续减半来做到这一点,直到它们之间的差值最多接近零(对于这个值,我使用了 foundroot 变量),在这种情况下,已找到根。

这个过程是通过递归findaroot方法完成的,参数为x1和x2(区间边距)。

这是该方法的工作原理:

  1. 该方法首先检查 f(x1) 和 f(x2) 的值(函数在 x1 和 x2 中的值)是否具有相同的符号,此时区间内没有根,返回noroot值;

  2. 然后,它检查是否找到了根(如果x1-x2foundroot);

  3. 如果未找到根,则返回其中一个间隔的返回值之间的最小值,在我的情况下,noroot 是一个非常高的数字。当然,如果 root 超过 noroot 的值,这将不起作用。

我的问题是:

  • 正如一般性问题所述,除了将返回值与高/低/不易获得的数字进行比较之外,我应该如何使该方法适用于所有情况?

这是我写的代码:

    //found root variable + value assigned if root is not found in interval (x1,x2)
    static final double foundroot = 0.000001;
    static final double noroot=999999;

    //finds root
    static double findaroot(double x1, double x2)
    {
        if(  Math.signum( f(x1,0) ) == Math.signum( f(x2,0) )  )
        {
            return noroot;
        }
        else
        {
            if(Math.abs(x1-x2)<=foundroot)
            {
                return x1;
            }
            else
            {
                return Math.min( findaroot(x1,(x1+x2)/2) , findaroot((x1+x2)/2,x2));
            }
        }
    }

如果有任何不清楚的地方,请询问。如果您认为我的问题/标题不具体或不清楚,请告诉我如何修改它们。

我将尽我所能做出澄清,以提供清晰的描述,并希望提供清晰的答案。

谢谢!

【问题讨论】:

    标签: java recursion divide-and-conquer


    【解决方案1】:

    可以通过使用有意义的返回值来避免使用幻数(无根)。在这种情况下,您可以考虑切换到 Double 而不是 double,并将空值用作“无结果”指示符。

    这可以通用:如果您使用递归函数来计算某个结果,但也需要转义,则使用空值是可接受的转义。如果您需要超过 1 次转义,您也可以考虑复合答案(例如,无法找到决定没有答案的原因)。在这种情况下使用一个对象来构造你的结果。

    所以在这种情况下,将你的函数更改为例如

    static final double threshold = 0.000001;
    
    //finds root; returns null if none is found
    static Double findaroot(double x1, double x2)
    {
        if(  Math.signum( f(x1,0) ) == Math.signum( f(x2,0) )  )
        {
            return null;
        }
        else
        {
            if(Math.abs(x1-x2)<=threshold)
            {
                return x1;
            }
            else
            {
                return Math.min( findaroot(x1,(x1+x2)/2) , findaroot((x1+x2)/2,x2));
            }
        }
    }
    

    【讨论】:

    • 确实,这回答了我的问题,所以我会将您的回答标记为已接受。我将最后一个 else 更改为 else {if(left half==null) {return right half} else {return left half}} 而不是 return Math.min(...)。有什么办法可以修改它,使该方法不会运行两次(一次在 if 中,一次在 return 中)?抱歉代码不好,我似乎无法在 cmets 中发布像样的代码。
    猜你喜欢
    • 1970-01-01
    • 2019-09-16
    • 2015-02-25
    相关资源
    最近更新 更多