簡體   English   中英

Lua與Java的遞歸

[英]Recursion in Lua vs. Java

我有一個遞歸算法(以三種不同的形式),它計算前n個奇數正整數的總和。 這些算法僅供學習,我知道有更好的方法可以解決這個問題。 我已經在Lua和Java中編寫了三個變體,我將其稱為Lua 1,Lua 2,Lua 3和Java 1,Java 2和Java 3.前兩個非常相似,只是重新排列。

Lua程序在這里 ,Java程序在這里

Lua 1和2表現非常好,很容易達到n = 100,000,000。 Lua 3遇到堆棧溢出,其中n> 16,000。

Java 1只能在達到堆棧溢出之前達到n = 4000而Java 2達到9000.在再次遇到堆棧溢出之前,Java 3設法達到n = 15,000。

誰能解釋這些結果? 為什么Java 1,2和3表現如此糟糕而Lua 1和2表現如此之好?

Lua做尾聲消除 例如,這樣的函數:

function foo (n)
    if n > 0 then return foo(n - 1) end
end

會不會導致堆棧溢出無論什么價值n您呼叫。

在Lua中,只有一個帶有return func(args)形式的調用是尾調用,就像你的前兩個Lua程序那樣。 但在第三個Lua計划中:

return (sumOdds3(n-1)) + (2*n - 1)

Lua在返回之前仍然需要進行計算,所以沒有正確的尾調用。

Java不是為遞歸算法設計的。 特別是它不支持常見的優化,如尾調用優化。

Java更適合使用循環,通常更快,並且通常使用簡單循環很簡單。

如果你使用迭代和Deque,你應該很好, n的值幾乎沒有限制

當您運行非常低效的代碼時,您傾向於發現無論是一種情況還是其他情況都可以優化低效率的方式可以產生很大的不同。

一種更有效的方法

// function to compute the sum of the first n odd positive integers
public static long sumOdds(long n) {
    long sumAll = n * (n + 1)/2;
    long sumEven = n/2 * (n/2 + 1);
    return sumAll - sumEven;
}
public static void main(String[] args) throws Exception {
    sumOdds(1);

    long start = System.nanoTime();
    long l = sumOdds(Integer.MAX_VALUE);
    long time = System.nanoTime() - start;
    System.out.printf("sumOdds(%,d) took %,d ns%n", Integer.MAX_VALUE, time);
}

版畫

sumOdds(2,147,483,647) took 343 ns

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM