【问题标题】:When are the multiplications done in this recursive factorial function?什么时候在这个递归阶乘函数中进行乘法运算?
【发布时间】:2013-11-03 23:06:00
【问题描述】:

我正在尝试理解以下问题:

public class Main {
    public static int fact(int n){
        if (n == 0){
            return 1;
        }else{
            return n * fact(n - 1);
        }
    }
    public static void main(String[] args){
      System.out.print(fact(5));
    }
}

当编译器通过并执行 return n * fact(n - 1); 时,它实际上是乘以 n 还是仅在达到基本情况后才这样做,然后乘以存储在堆栈中的所有值?

请注意,我对这种递归编码方式仍然很陌生。

【问题讨论】:

  • 一些简单的调试和/或添加产生输出的语句会揭示很多。
  • 我知道,但这就是我不断得到的结果:与目标 VM 断开连接,地址:'127.0.0.1:55768',传输:'socket'
  • 查看乘法执行顺序的好方法是将n * fact(...) 替换为mult(n, fact(...)),其中mult 是您编写的一种方法,它接受两个数字并返回它们的乘积。然后你可以在mult中添加一些输出打印,并查看调用的顺序。

标签: java math recursion stack


【解决方案1】:

查看乘法执行顺序的好方法是将n * fact(...) 替换为mult(n, fact(...)),其中mult 是您编写的一个方法,它接受两个数字并返回它们的乘积。然后您可以在mult 中添加一些输出打印,并查看调用的顺序。

public class FactorialExample {
    // The new mult method.
    private static int mult( final int x, final int y ) {
        System.out.println( "Multiplying "+x+" and "+y+"." );
        return x * y;
    }

    public static int fact(int n){
        if (n == 0){
            return 1;
        }else{
            return mult(n, fact(n - 1)); // using the new mult method
        }
    }

    public static void main(String[] args){
      System.out.print(fact(5));
    }
}

这会产生以下输出:

Multiplying 1 and 1.
Multiplying 2 and 1.
Multiplying 3 and 2.
Multiplying 4 and 6.
Multiplying 5 and 24.
120

回想一下,左加数是对应于n 的那个,并且对fact第一个 调用具有最大值。因此,递归调用 fact(4) 必须首先完成(生成 24),然后将 524 相乘。

【讨论】:

    【解决方案2】:

    (注意:编译器不是评估fact的程序;程序本身就是这样做的)。

    程序遇到语句时

    n * fact(n - 1)
    

    它将通过调用fact 并将n - 1 作为参数传递来单独计算fact(n - 1)。一旦该函数完成运行并返回,它将具有一个可以乘以n 的值。这样做的最终效果是,直到达到基本情况之后才会执行乘法运算,此时存储在堆栈中的n 的值将全部相乘。您可以通过在该行放置一个断点来看到这一点

    return n * fact(n - 1);
    

    并观察程序展开递归以计算整体值。

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:
      1. java tries to output unknown value, so java execute fact with N = 5
        2. tries to multiple 5 by value, which is unknown, it executes fact with N=5-1
          3. tries to multiple 4 by value ..... N=3
            4. tries to multiple 3 by value ..... N=2
              5. tries to multiple 2 by value ..... N=1
                6. tries to multiple 1 by value ..... N=0
                  7. returns 1 and go back to 6th item
                8. 1*1 = 1 and go back to 5th item
              9. 2*1 = 2 and go back to 4th item
            10. 3*2 = 6 and go back to 3rd item
          11. 4*6 = 24 and go back to 2nd item
        12. 5*24 = 120 and return to 1st item
      13. display 120
      

      【讨论】:

      • "3. 尝试将 4 乘以值..... N=3" 为什么它会尝试而不是实际执行?
      • @user2895567 因为java暂时不知道值,它应该执行函数来获取乘法的第二个值
      【解决方案4】:

      一旦fact(n - 1) 被评估,它将乘以nfact(n - 1)(直到你达到基本情况。

      递归的 fact() 调用被链接在一起,直到最后一个有东西要返回。

      【讨论】:

        【解决方案5】:

        这是简单的递归。与任何递归一样,它首先深入到基本情况(使用堆栈),然后进行乘法(在堆栈展开过程中)

        那么,在你的例子中会发生什么,即事实(5)

        fact(5) --> 5 * fact(4) // Here another recursive call is made to calculate fact(4)
        fact(4) --> 4 * fact(3)//Here another recursive call is made to calculate fact(3)
        .
        .
        .
        fact(1) --> 1 * fact(0)// fact(0) is 1 as per your code
        

        从此时开始,堆栈展开,每个fact(n) 现在都由其简化版本表示。到底 fact(5) --> 5 * fact(4) 转换为 fact(5) --> 5 * 4 * 3 *2 *1

        【讨论】:

          猜你喜欢
          • 2015-01-08
          • 2019-08-06
          • 1970-01-01
          • 2015-04-19
          • 1970-01-01
          • 2015-04-16
          • 1970-01-01
          • 1970-01-01
          • 2018-06-24
          相关资源
          最近更新 更多