2011-11-18 90 views
24

我正在使用Java:The Complete Reference這本書學習Java。 目前我正在研究主題遞歸。在Java中使用遞歸的因子

請注意:在stackoverflow上也有類似的問題。我搜查了他們,但我沒有找到解決我的問題。我對以下程序中的邏輯感到困惑。

如果我運行下面的程序,它會產生正確的輸出,但我不理解邏輯。

  • 我不明白以下行中的邏輯:result = fact(n-1)* n;
  • 從我所知,如果我們通過n值= 4如圖中下面程序,
  • 然後,將3×4被存儲在結果即12
  • 再次,事實(正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); 
    } 
} 
+1

我的建議是在深入研究Java之前,首先需要了解遞歸背後的數學。如果你還沒有這樣做,這對你來說將是一個非常好的開始en.wikipedia.org/wiki/Recursion – GETah

+1

希望這可以讓你更清楚http://www.programmerinterview.com/index。PHP /遞歸/遞歸解釋/ – Rangesh

回答

9

resultfact方法的局部變量。所以每次調用事實方法時,結果都會存儲在與以前的事實調用不同的變量中。

所以,當事實與3調用作爲參數,你可以想像,其結果是

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

你的困惑,我相信,來自於一個事實,你覺得只有一個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; 

希望它更清晰了。

+0

雅,你明白了我的觀點。你能否詳細說明一下。 – user907629

2

的關鍵點,你在這裏缺少的是變量「結果」是一個堆棧變量,因此它不會被「替換」。詳細說明,每次調用事實時,都會在解釋器內部創建一個名爲「result」的NEW變量,並鏈接到該方法的調用。這與鏈接到對象實例的對象字段相反,而不是特定的方法調用

46

首先,您應該瞭解factorial是如何工作的。

讓我們拿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 

我希望你明白了吧。

+0

我認爲你的意思是// n = 4並且不等於1.不知道12從哪裏來。 – Gray

+0

是..編輯..謝謝.. –

+0

我的意思是,階乘4 = 4 * 3 * 2 * 1.我的問題,起初我認爲值4 * 3將被存儲在結果中。 – user907629

5

會發生什麼是遞歸調用本身導致進一步的遞歸行爲。如果你寫出來,你會得到:

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

雖然這是舊的,它仍然繼續在谷歌很好。所以我想我會提到這一點。沒有人提到檢查什麼時候x = 0

0!和1!兩者都= 1.

這不是與以前的答案進行檢查,並會導致堆棧溢出,如果事實(0)運行。反正簡單的修復:

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

不要再創建一個變量

結果

簡單

回報的事實(N-1)* N;

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

     if(n==1) 
     return 1; 

     return fact(n-1) * n; 

    } 
} 
-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; 
    } 
} 
0

在我看來,這是有人用java初學知識水平的意見,我建議第n == 1改變到n < = 1(N == 0)||(n == 1),因爲0的階乘是1.

-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 
    } 
} 
1

使用三元運算符的遞歸解決方案。

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

返回n == 1 || n == 0? 1:n * fac(n-1); – ggb667

+0

return(n <= 1)? 1:n * fact(n-1) –

0

正確的是:

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

這將返回1 0的階乘就做相信我。我已經學會了這個難題。 只是爲了保持0的條件無法清除採訪。

0

要了解它,你必須聲明中可能最簡單的方式方法和martynas釘它在5月6日一篇:

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

閱讀上面的實現,你就明白了。

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); 
    } 
} 
+1

請讓我知道爲什麼downvote? – SanA

+1

很可能是因爲你沒有解釋任何東西,但我喜歡你的解決方案,並且我已經投了票。 – another

10

這裏又是如何階乘計算使用遞歸作品的另一種解釋。

讓我們稍微修改源代碼:

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

-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); 
} 
} 
+1

添加一些解釋與答案如何幫助解決當前問題 –

-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資源使用遞歸找到一個數的階乘例子。