2011-04-04 243 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