2011-04-04 227 views
3

我有2個函數來計算n! (階乘)。第一個是遞歸函數,第二個是直線循環。我已經在jsperf.com中測試過他們的表現。對於我測試的所有瀏覽器,除了IE(測試版本爲v7,8 en 9)外,非遞歸函數的性能優於遞歸函數。現在我非常習慣IE和jscript作爲例外,但在這種情況下,我是拙劣的:可能是造成差異的原因(換句話說,如果我希望我的因子在每個瀏覽器中都很快,我必須真的首先檢查瀏覽器;)?性能:遞歸 - 非遞歸(IE)

使用的功能是:

//recursive 
function factorial(n) { 
var result = 1,  
fac = function(n) {  
     return result *= n, n--, (n > 1 ? fac(n) : result);  
     }; 
return fac(n); 
} 
//nonrecursive 
function factorialnr(n){ 
    var r = n; 
    while (--n > 1) { 
    r *= r != n ? n : 1; 
    } 
    return r; 
} 
+1

嘗試用r = r *(...)替換r * =,因爲對於複合運算符,IE很慢。還可以嘗試放入一個if循環而不是三元運算符 - 更簡單時,更多的代碼通常會更快。哦,在IE 6中,非遞歸版本比遞歸版本快7倍。 – RobG 2011-04-04 06:39:08

+1

由於您在第一個條件測試中已經減少了'n',所以'r!= n'總是成立。 – Gumbo 2011-04-04 06:42:10

+1

http://jsperf.com/factorial-recursive-vs-not-recursive/2這樣做,但沒有區別。 – KooiInc 2011-04-04 06:43:15

回答

0

我進一步看了,但couln't找到關於這個問題的任何東西。經過測試,似乎在刪除jsperf test版本1中的三元組後,IE的行爲與其他瀏覽器類似(請參閱rev 5 of the jsperf-test)。但測試ternary on it's own並沒有真正顯示出差異。

好了,讓我們把它留給那個。我在這裏學到的是,看看遞歸函數是否可以用迭代方式重寫是明智的。後者似乎超過遞歸。

感謝您的回答,非常感謝。

1

大概是因爲瀏覽器無法優化tail recursion。它沒有意識到你的lambda函數可以迭代地重寫並消除函數調用的開銷。

瀏覽器是不是真的意味着要完全成熟的編譯器和我不希望他們能夠執行所有傳統的編譯器進行優化。如果某個瀏覽器可以執行特定的優化,那太棒了。但這並不意味着所有的意願。

+0

試過,以及 - http:// jsperf .com/factorial-recursive-vs-not-recursive/3。如果我做對了,尾遞歸沒有太大的作用。 – Kobi 2011-04-04 06:45:52

+0

不,我的意思是,lambda函數也使用尾遞歸。這可能是因爲它很慢。 – jeffythedragonslayer 2011-04-04 06:47:37

+0

這個問題不是關於遞歸本身,而是關於所有(測試過的)瀏覽器的原因,但IE *使用階乘的迭代函數更快。 – KooiInc 2011-04-04 09:01:38