[英]how this code execute in compiler?
我是 Java 新手,正在閱讀有關它的幾本書。 我無法弄清楚這段代碼的輸出是如何產生的:
import java.util.*;
class myclass {
public static void main(String[] args) {
Scanner myScanner = new Scanner(System.in);
System.out.println(factorial(myScanner.nextInt())+"\n");
}
public static int factorial(int n) {
if (n==0) {
return 1;
} else {
int recurse = factorial(n-1);
int result = recurse*n;
return result;
}
}
}
任何人都可以為我一步一步地解釋這個嗎? 我了解主要方法和Scanner
類,但我不明白當我在輸入處輸入一個像8
這樣的整數時,我在輸出處得到40320
。
函數factorial使用遞歸來求解階乘。 這意味着該函數多次調用自身,直到 n 變為 0(其中它返回 1)。
因此,對於 n = 3,程序首先將結果設置為
Factorial(3) = factorial(2) * 3,
Factorial(2) = factorial(1) * 2,
Factorial(1) = factorial(0) * 1,
Factorial(0) = 1 (Because of the *if-statement*)
現在您可以將這些東西加在一起,因為它知道 Factorial(0)、Factorial(1)、Factorial(2) 和 Factorial(3) 是什么。
然后變成:
Factorial(0) = 1,
Factorial(1) = 1 * 1 = 1,
Factorial(2) = 1 * 2 = 2,
Factorial(3) = 2 * 3 = 6
首先:階乘函數
我想你不了解遞歸階乘函數。
函數聲明:
public static int factorial(int n){
0 的階乘是 1(例外):
if(n==0){
return 1;
}
如果用戶介紹的數字不為 0,則:
else {
int recurse = factorial(n-1);
int result = recurse*n;
return result;
}
在這種情況下,例如使用recurse = factorial(2-1)
調用函數,等待直到對函數的調用結束(在這種情況下調用的是同一個函數,但它不是問題,只需等待直到函數調用結束)。 因此調用階乘(2-1)。 未完待續...
factorial(1), n==0
false ,因此進入 else 語句。 調用階乘(1-1)。 再等一次,直到函數 factorial(1-1) 結束。 未完待續...
factorial(0), n==0
true ,因此return 1
。 對函數的調用結束,現在我們將繼續第 2 步。
在步驟 2 中繼續 factorial(1): factorial(1-1) 返回 1 並將其存儲在recurse
。 int result = recurse * n
所以結果 = 1·1。 最后在這一步返回result
(1)。 現在我們轉到第 1 步,該步驟仍在 factorial(1) 調用中等待。
在步驟 1 中繼續 factorial(2): factorial(2-1) 返回 1 並將其存儲在recurse
。 int result = recurse * n
所以結果 = 1·2。 並返回result
(2)。
最后 factorial(2) 返回 2. 想想 factorial(3), 4, 5, 6, 7, 最后你就會明白 factorial 8. 最重要的是,當你在你所在的地方調用同一個函數時,它將狀態保存在堆棧中並等待它完成。
當您正確格式化代碼時,代碼更容易處理,所以請在將來這樣做。 有時,當您使代碼更簡潔時,代碼也更容易處理。 請注意,您可以“內聯” result
變量:
public static int factorial(int n) {
if (n == 0) {
return 1;
}
else {
int recurse = factorial(n - 1);
return recurse * n;
}
}
或者更簡單:
public static int factorial(int n) {
if (n == 0) {
return 1;
}
return n * factorial(n-1);
}
現在讓我們嘗試一些值。 讓我們嘗試使用“0”的值:
public static int factorial(int n) {
if (n == 0) {
return 1; //<-- Returns 1
}
return n * factorial(n-1);
}
好的,沒錯:0! = 1。
讓我們嘗試使用“1”的值:
public static int factorial(int n) {
if (n == 0) {
return 1; //not reached
}
return n * factorial(n-1); //<-- 1 * factorial(0) = 1 * 1 = 1
}
好:1! = 1。
讓我們嘗試使用“8”的值:
public static int factorial(int n) {
if (n == 0) {
return 1; //not reached
}
return n * factorial(n-1); //<-- 8 * factorial(8-1) = 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 40320
}
這是有道理的,因為 8! = 40,320。
這樣做的方式稱為遞歸,因為該方法本質上是在調用自身。 如果做得好,遞歸是編程的一個美麗部分,因為代碼通常相當簡潔,並且是一種“分而治之”的心態。 這是編程中的一個介紹性概念。
一個好的程序員總是會考慮價值體系。 因此,在這種情況下,例如,如果 n 為 -1,您的函數將提供StackOverFlow
錯誤。 (您可以將代碼更改為讀取if (n <= 1)
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.