繁体   English   中英

“对于y在range(1,x)中”循环运行时间太长。 如何在Python中加快这一过程?

[英]“For y in range(1,x)” loops taking too long to run. How can one expedite this process in Python?

此代码需要40秒钟才能以1000的订单运行。我需要在order = 100,000,000时运行它。 有没有办法让我加快这段代码的速度?

from fractions import Fraction

x=5
order=1000
count=0
while x <=order:
    for y in range(1,x):
        if str(Fraction(y/x).limit_denominator()) != "%s/%s"%(y,x):
            print(Fraction(y/x).limit_denominator())
            count += 1
    print(" ")
    x+=1

count= (count + 1) * 6 + (order -1)*6
print(count)

这段代码的目的是破译Euler项目上的问题351。 我对Python的了解有限,因此我尝试用我所知道的来弄清楚它。 最初,我发现每行隐藏的绿色点都很容易找到( (n-1)* 6 ),但是确定中心点是一个更大的挑战。 找出每个受阻绿点的图案不是线性的,而是要考虑将六个当前三角形中的每个三角形的行视为分数,然后找到可以简化的分数。 此代码解析三角形的每个“行”以简化分数。 如果找到一个,则代码将1加到变量'count'。 由于while循环从第5行开始(在第一个绿色点之后1行),我不得不将这些点添加回末尾的最终计数( (count + 1)* 6 )。 我使用此代码来确认找到的绿点数量大约为1000。不过运行了40秒。 截至2018年1月11日美国东部标准时间(EST),我已经在计算机上运行1亿天半了,这100,000,000可能需要更长的时间(从几天到几周。)

正如其他人所提到的,您的算法具有很差的复杂度,但是您也使用Fraction错误。 使用两个参数的版本,并且绝对不要转换和比较字符串。 您也没有充分的理由两次构造和调用Fraction(y/x).limit_denominator()

这将极大地加快代码的速度,但是并不能解决算法的复杂性:

order = 1000
x = 5
count = 0
while x <= order:
    for y in range(1, x):
        frac = Fraction(y, x)  # don't use y/x
        if frac.numerator != y:
            # print(frac)  # if you *must* print, reuse this
            count += 1
    # print(" ")
    x += 1

count = (count + 1) * 6 + (order - 1) * 6
print(count)

问题不是Python; 这是你的算法。

要分析运行时解决方案,首先需要使自己熟悉渐近复杂性 ,通常用Big-O表示法进行描述。

Big-O表示法描述了运行时间如何随着输入n的大小的变化而变化( O(n) )。

下面是带有示例的常见Big-O运行时:

O(1)-运行时不依赖于数组的大小(无论大小都恒定时间)。

int myarray[] = //fill array with values
cout << myarray.length;

O(N)-运行时间与数组大小成正比。

int myarray[] = //fill array with values
for(int i = 0; i<n; i++) cout << myarray[i] << " ";

O(N ^ 2)-运行时间与数组的平方大小成正比。

int myarray[] = //fill array with values
for(int i = 0; i<n; i++) {
    for(int j = 0; j<n; j++) {
        cout << myarray[i]+myarray[j] << endl;
//print the sum of every possible pairing of digits in array (with repeats)

因此,如果我们知道O(n)运行时,我们就能预测算法要花多长时间才能运行。 您的算法为O(n ^ 2),因为它使用while循环迭代到1000(n),而第二个嵌套的for循环迭代直到x。 我们无视for循环最多迭代x,因为它不是渐近有效的。

现在我们看到您的算法太慢了。 100,000,000 ^ 2是一个很大的数字,因此必须改进您的算法。

请注意, O(n*logn)的运行时将导致800,000,000(n = 100,000,000),这将在大约10秒内运行(给定或取决于常量因素,语言等),这是更加合理的。

根据问题的不同,如果您对存储数据的方式很聪明,甚至可以减少算法以线性时间( O(n) )运行。 无论哪种方式,您当前的算法都太慢了。 回到绘图板!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM