使用Java中的递归的因子

时间:2011-11-18 13:48:53

标签: java recursion

我正在使用Java:The Complete Reference这本书学习Java。 目前我正在研究Recursion主题。

请注意: stackoverflow上有类似的问题。我搜索了他们,但我没有找到我的问题的解决方案。我对以下程序中的逻辑感到困惑。

如果我运行以下程序,它会产生正确的输出,但我不理解逻辑。

  • 我不理解以下行中的逻辑: result = fact(n-1)* n;
  • 据我所知,如果我们传递n = 4的值,如下面的程序所示,
  • 然后,将3 * 4存储在结果中,即12.
  • 再次,调用事实(n-1)。然后n变为3。
  • 然后将2 * 3存储在替换前12个的结果中。
  • 我想你明白我被困在哪里/困惑。

  • 谢谢。

class Calculation
{
    int fact(int n)
    {
        int result;

       if(n==1)
         return 1;

       result = fact(n-1) * n;
       return result;
    }
}

public class Factorial
{
     public static void main(String args[])
     {
       Calculation obj_one = new Calculation();

       int a = obj_one.fact(4);
       System.out.println("The factorial of the number is : " + a);
     }
}

19 个答案:

答案 0 :(得分:50)

首先,您应该了解因子如何运作。

让我们拿4!举个例子。

4! = 4 * 3 * 2 * 1 = 24

让我们使用上面的示例模拟代码:

int fact(int n)
    {
        int result;
       if(n==0 || n==1)
         return 1;

       result = fact(n-1) * n;
       return result;
    }

在大多数编程语言中,我们称之为function stack。它就像一副牌,每张牌都放在另一张牌之上 - 每张牌都可以被认为是一种功能所以传递方法fact

堆叠等级1:fact(4) // n = 4 and is not equal to 1. So we call fact(n-1)*n

堆叠等级2:fact(3)

筹码等级3:fact(2)

堆栈等级4:fact(1) //现在,n = 1.所以我们从这个函数返回1。

返回值...

筹码等级3:2 * fact(1) = 2 * 1 = 2

堆叠等级2:3 * fact(2) = 3 * 2 = 6

堆叠等级1:4 * fact(3) = 4 * 6 = 24

所以我们24岁了。

请注意以下几点:

result = fact(n-1) * n;
           return result;

或简单地说:

return fact(n-1) * n;

这会调用函数本身。以4为例,

按顺序排列..

return fact(3) * 4;
return fact(2) * 3 * 4
return fact(1) * 2 * 3 * 4

代替结果......

return 1 * 2 * 3 * 4 = return 24

我希望你明白这一点。

答案 1 :(得分:17)

这是对使用递归的因子计算如何工作的另一种解释。

让我们稍微修改源代码:

int factorial(int n) {
      if (n <= 1)
            return 1;
      else
            return n * factorial(n - 1);
}

以下是详细计算 3!

enter image description here

来源:RECURSION (Java, C++) | Algorithms and Data Structures

答案 2 :(得分:10)

resultfact方法的局部变量。因此,每次调用事实方法时,结果都存储在与先前事实调用不同的变量中。

因此,当使用3作为参数调用fact时,您可以想象它的结果是

 result3 = fact(2) * 3
 result3 = result2 * 3
 result3 = 1 * 2 * 3

答案 3 :(得分:9)

我相信,您的困惑来自于您认为只有一个result变量,而实际上每个函数调用都有一个result变量。因此,旧的结果不会被替换,而是返回。

要精通:

int fact(int n)
{
    int result;

   if(n==1)
     return 1;

   result = fact(n-1) * n;
   return result;
}

假设打电话给fact(2)

int result;
if ( n == 1 ) // false, go to next statement
result = fact(1) * 2; // calls fact(1):
|    
|fact(1)
|    int result;  //different variable
|    if ( n == 1 )  // true
|        return 1;  // this will return 1, i.e. call to fact(1) is 1
result = 1 * 2; // because fact(1) = 1
return 2;

希望现在更清楚了。

答案 4 :(得分:5)

递归调用本身会导致进一步的递归行为。如果你要写出来,你会得到:

 fact(4)
 fact(3) * 4;
 (fact(2) * 3) * 4;
 ((fact(1) * 2) * 3) * 4;
 ((1 * 2) * 3) * 4;

答案 5 :(得分:5)

public class Factorial {

    public static void main(String[] args) {
        System.out.println(factorial(4));
    }

    private static long factorial(int i) {

        if(i<0)  throw new IllegalArgumentException("x must be >= 0"); 
        return i==0||i==1? 1:i*factorial(i-1);
    }
}

答案 6 :(得分:3)

这里缺少的关键点是变量“result”是一个堆栈变量,因此它不会被“替换”。详细说明,每次调用事实时,在解释器内部创建一个名为“result”的NEW变量,并将其链接到方法的调用。这与链接到对象实例的对象字段形成对比,而不是特定的方法调用

答案 7 :(得分:1)

尽管这已经过时了,但谷歌仍然会很好。所以我想我会提到这一点。没人提到要检查 x = 0 的时间。

0!和1!两者= 1.

如果运行了fact(0),则不会使用之前的答案检查,并且会导致堆栈溢出。无论如何简单的修复:

public static int fact(int x){
    if (x==1 | x==0)
        return 1;
    return fact(x-1) * x;
}// fact

答案 8 :(得分:1)

使用三元运算符的递归解决方案。

public static int fac(int n) {
    return (n < 1) ? 1 : n*fac(n-1);
}

答案 9 :(得分:0)

使用Java 8及更高版本,并使用递归本身

  UnaryOperator<Long> fact = num -> num<1 ? 1 : num * this.fact.apply(num-1);

并像使用它

  fact.apply(5); // prints 120

内部计算方式类似

5*(4*(3*(2*(1*(1)))))

答案 10 :(得分:0)

恕我直言,了解与递归相关的行动的关键是:

  1. 首先,我们以递归方式进入堆栈,并且每次调用我们 以某种方式修改一个值(例如func(n-1);中的 n-1 ),确定是否 递归应该越来越深。
  2. 一旦 满足recursionStopCondition(例如n == 0),递归停止, 和方法执行实际工作并将值返回给调用者方法 上层堆栈,因此冒泡到堆栈顶部。
  3. 是的 不知何故,抓住从更深堆栈返回的值很重要 修改它(在你的情况下乘以n),然后返回它 修改后的值超过堆栈。常见的错误是 来自最深堆栈帧的值直接返回到顶部 堆栈,以便忽略所有方法调用。
  4. 当然,方法可以在潜入(从堆栈的顶部到底部)或返回途中进行有用的工作。

答案 11 :(得分:0)

要理解它,你必须以最简单的方式声明方法,并且马丁纳斯于5月6日发布了它:

int fact(int n) {
    if(n==0) return 1;
    else return n * fact(n-1);
}

阅读上面的实现,你会明白的。

答案 12 :(得分:0)

正确的是:

int factorial(int n)
{
    if(n==0||n==1)
        return 1;
    else 
        return n*factorial(n-1);
}

对于因子0,这将返回1.它是否相信我。我很难学到这一点。 只是因为没有保持0的条件无法清除面试。

答案 13 :(得分:0)

在我看来,这是初学者对java知识的看法,我建议将n == 1改为n <= 1或(n == 0)||(n) == 1)因为0的阶乘是1.

答案 14 :(得分:-1)

public class Factorial2 {
    public static long factorial(long x) {
        if (x < 0) 
            throw new IllegalArgumentException("x must be >= 0");
        if (x <= 1) 
            return 1;  // Stop recursing here
        else 
           return x * factorial(x-1);  // Recurse by calling ourselves
    }
}

答案 15 :(得分:-1)

public class Factorial {
public static void main(String[] args) {
   int n = 7;
   int result = 1;
   for (int i = 1; i <= n; i++) {
       result = result * i;
   }
   System.out.println("The factorial of 7 is " + result);
}
}

答案 16 :(得分:-1)

这里是使用递归找到数字的阶乘的逻辑,

static int factorialFunction(int n)
{
    int result;
    if(n == 1)
    {
       return 1;
    }
    // here we are calling the recursion function
    result = factorialFunction(n - 1) * n;
    return result;
}

与此同时,您可以使用递归来引用this资源以查找有关数字的阶乘的示例。

答案 17 :(得分:-1)

import java.util.Scanner;

public class Factorial {
    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        int n; 
        System.out.println("Enter number: ");
        n = keyboard.nextInt();
        int number = calculatefactorial(n);
        System.out.println("Factorial: " +number);
    }
    public static int calculatefactorial(int n){
        int factorialnumbers=1;
        while(n>0){
         factorialnumbers=(int)(factorialnumbers*n--);   
        }
        return factorialnumbers;
    }
}

答案 18 :(得分:-1)

不要再创建一个变量

  

结果

简单

  

返回事实(n-1)* n;

class Calculation
{
    int fact(int n)
    {
        int result;

       if(n==1)
         return 1;

       return fact(n-1) * n;

    }
}