内置函数与递归函数

时间:2016-06-28 11:17:05

标签: python python-3.x

我不是数学家,也不是计算机科学家 - 只是一个业余爱好者程序员,我正在尝试通过执行Euler项目问题​​来教自己Python。其中一个需要使用阶乘。我使用递归函数编写了自己的计算,然后意识到可能有一个我可以使用的内置函数。找到它后我想我会看到它比我的递归函数快多少。令我惊讶的是,我发现它实际上更慢。

这会让任何人感到惊讶吗?我很好奇。

我附上了我的代码(为了更好的衡量,我还提供了一个循环方法以进行额外的比较)。

import math
import time

x = 50

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)

secs = time.clock()
print(math.factorial(x))
print ("The built-in function took {a:0.5f} seconds.".format(a = time.clock() - secs)) 

secs = time.clock()
print (factorial(x))
print ("The recursive function took {a:0.5f} seconds.".format(a = time.clock() - secs))

secs = time.clock()
factl = 1
for i in range (1,x+1):
    factl *= i
print (factl)
print ("The loop method took {a:0.5f} seconds.".format(a = time.clock() - secs))

输出:

30414093201713378043612608166064768844377641568960512000000000000

内置功能耗时0.00549秒。

30414093201713378043612608166064768844377641568960512000000000000

递归函数耗时0.00299秒。

30414093201713378043612608166064768844377641568960512000000000000

循环方法耗时0.00259秒。

3 个答案:

答案 0 :(得分:6)

我拿了你的代码,并且多次改变了测试这三种方法的顺序。我注意到测试的第一种方法通常花费的时间是第二种方法的两倍。

我无法解释原因,但我确实知道你无法通过一次迭代测量函数的性能。您必须多次重复该功能并计算平均时间。

IPython带有一个方便的“魔术方法”timeit就是这样做的:

print('math')
%timeit math.factorial(x)

print('factorial')
%timeit factorial(x)

print('loop')
%timeit loopmethod(x)

输出:

  

数学
  最慢的运行时间比最快的运行时间长33.62倍。这可能意味着缓存了中间结果   1000000个循环,最佳3:每循环1.25μs

     

阶乘
  100000个循环,最佳3:每循环19.4μs

     


  100000次循环,最佳3:7.87μs/循环

内置函数的平均速度比递归函数快10倍。

答案 1 :(得分:3)

即使不使用分析库,您也可以通过调整代码来看到内置方法比递归方法更好,这样它就不会打印时间:

import math
import time

x = 50

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)

secs = time.clock()
f = math.factorial(x)
elapsed = time.clock() - secs
print(f)
print ("The built-in function took {a:0.5f} seconds.".format(a = elapsed))

secs = time.clock()
f = factorial(x)
elapsed = time.clock() - secs
print (f)
print ("The recursive function took {a:0.5f} seconds.".format(a = elapsed))

secs = time.clock()
factl = 1
for i in range (1,x+1):
    factl *= i
elapsed = time.clock() - secs
print (factl)
print ("The loop method took {a:0.5f} seconds.".format(a = elapsed))

典型运行:

30414093201713378043612608166064768844377641568960512000000000000
The built-in function took 0.00001 seconds.
30414093201713378043612608166064768844377641568960512000000000000
The recursive function took 0.00011 seconds.
30414093201713378043612608166064768844377641568960512000000000000
The loop method took 0.00004 seconds.

答案 2 :(得分:2)

为了更好地比较不同功能的效率,您需要在较长时间内多次运行测试,同时在它们之间进行交替,并为每个被测试的功能花费最快的时间。

由于在后台运行的进程的活动,执行时间可能会因当前计算机负载而有很大差异。为每个被测试的功能花费最快的时间应该最小化由于同时运行的其他进程导致的任何中断的影响。输入/输出操作(例如打印到终端)比较耗时,因此我建议只运行factorial(x)而不是print (factorial(x))

您还可以查看Python 3 profilers library,它专门用于报告程序各个部分的执行时间。对于基准标记单个函数,timeit模块更合适。