gpt4 book ai didi

python - 优化分区函数

转载 作者:太空狗 更新时间:2023-10-29 21:47:54 24 4
gpt4 key购买 nike

这是Python代码:

# function for pentagonal numbers
def pent (n): return int((0.5*n)*((3*n)-1))

# function for generalized pentagonal numbers
def gen_pent (n): return pent(int(((-1)**(n+1))*(round((n+1)/2))))

# array for storing partitions - first ten already stored
partitions = [1, 1, 2, 3, 5, 7, 11, 15, 22, 30, 42]

# function to generate partitions
def partition (k):
if (k < len(partitions)): return partitions[k]

total, sign, i = 0, 1, 1

while (k - gen_pent(i)) >= 0:
sign = (-1)**(int((i-1)/2))
total += sign*(partition(k - gen_pent(i)))
i += 1

partitions.insert(k,total)
return total

它使用这种方法来计算分区:

p(k) = p(k − 1) + p(k − 2) − p(k  − 5) − p(k − 7) + p(k − 12) + p(k  − 15) ...

(来源:Wikipedia)

但是,当涉及到大数(超过 p(10^3)​​)时,代码会花费相当长的时间。我想问你我是否可以优化我的代码,或者提示我使用不同但更快的算法或方法。欢迎任何优化建议。

不,在你问之前,这不是为了家庭作业或欧拉计划,而是为了体验值(value)。

最佳答案

这里有一些评论。请注意,我不是这方面的专家,因为我也喜欢搞数学(和欧拉计划)。

我重新定义了五边形函数如下:

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 使用 float 会引入错误(比较 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,否则为 profile 模块)你可以看到你的代码花费大部分时间的地方。这是一个基于您的分区函数的示例。

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)

您可以在我的结果中看到没有调用 lenround 内置函数。而且我几乎将调用五边形函数(gen_pent_newpent_new)的次数减半

可能还有其他技巧可以提高 python 代码的速度。我会在这里搜索“python 优化”,看看您能找到什么。

最后,您提到的维基百科页面底部的链接之一是 academic paper关于计算分区数的快速算法。快速浏览一下就会发现它包含算法的伪代码。这些算法可能比你我能产生的任何东西都快。

关于python - 优化分区函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3164305/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com