这里有一些意见。请注意,我并不是这方面的专家,我也喜欢用数学(和欧拉项目)搞乱。
我已经重新定义了五角数功能如下:
def pent_new(n):
return (n*(3*n - 1))/2
def gen_pent_new(n):
if n%2:
i = (n + 1)/2
else:
i = -n/2
return pent_new(i)
我在这样的,我不会引入浮点计算的方式写他们 - 为大型用正花车将引入误差(比较结果为n = 100000001
)。
可以使用timeit模块测试代码片段。当我测试所有五角函数(你的和我的)时,我的结果更快。以下是测试您的gen_pent
函数的示例。
# Add this code to your script
t = Timer("for i in xrange(1, 100): gen_pent(i)", "from __main__ import gen_pent")
print t.timeit()
这是您的partition
函数的轻微修改。同样,使用timeit进行测试表明它比您的partition
函数更快。但是,这可能是由于对五角数函数的改进所致。
def partition_new(n):
try:
return partitions_new[n]
except IndexError:
total, sign, i = 0, 1, 1
k = gen_pent_new(i)
while n - k >= 0:
total += sign*partition_new(n - k)
i += 1
if i%2: sign *= -1
k = gen_pent_new(i)
partitions_new.insert(n, total)
return total
在你的分区函数中,你计算每个循环两次的一般五边形数。一次在while条件下测试,另一次更新total
。我将结果存储在一个变量中,因此每个循环只进行一次计算。
使用cProfile模块(对于Python> = 2.5,否则该形象模块),你可以看到你的代码花费大量的时间。这里是一个基于你的分区函数的例子。
import cProfile
import pstats
cProfile.run('partition(70)', 'partition.test')
p = pstats.Stats('partition.test')
p.sort_stats('name')
p.print_stats()
这产生在控制台窗口中下面的输出:
C:\Documents and Settings\ags97128\Desktop>test.py
Fri Jul 02 12:42:15 2010 partition.test
4652 function calls (4101 primitive calls) in 0.015 CPU seconds
Ordered by: function name
ncalls tottime percall cumtime percall filename:lineno(function)
552 0.001 0.000 0.001 0.000 {len}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
60 0.000 0.000 0.000 0.000 {method 'insert' of 'list' objects}
1 0.000 0.000 0.015 0.015 <string>:1(<module>)
1162 0.002 0.000 0.002 0.000 {round}
1162 0.006 0.000 0.009 0.000 C:\Documents and Settings\ags97128\Desktop\test.py:11(gen_pent)
552/1 0.005 0.000 0.015 0.015 C:\Documents and Settings\ags97128\Desktop\test.py:26(partition)
1162 0.002 0.000 0.002 0.000 C:\Documents and Settings\ags97128\Desktop\test.py:5(pent)
现在剖析我的分区功能:
Fri Jul 02 12:50:10 2010 partition.test
1836 function calls (1285 primitive calls) in 0.006 CPU seconds
Ordered by: function name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
60 0.000 0.000 0.000 0.000 {method 'insert' of 'list' objects}
1 0.000 0.000 0.006 0.006 <string>:1(<module>)
611 0.002 0.000 0.003 0.000 C:\Documents and Settings\ags97128\Desktop\test.py:14(gen_pent_new)
552/1 0.003 0.000 0.006 0.006 C:\Documents and Settings\ags97128\Desktop\test.py:40(partition_new)
611 0.001 0.000 0.001 0.000 C:\Documents and Settings\ags97128\Desktop\test.py:8(pent_new)
你可以在我的结果看到有到len
没有呼叫和内建函数。我几乎减半了五角函数的调用次数(gen_pent_new
和pent_new
)
提高python代码的速度可能还有其他技巧。我会在这里搜索'python优化',看看你能找到什么。
最后,您提到的维基百科页面底部的链接之一是用于计算分区号的快速算法的academic paper。快速浏览显示它包含算法的伪代码。这些算法可能比我们能够生成的任何东西都快。