简体   繁体   English

Python:for循环耗时太长

[英]Python: for loop taking too long

I'm trying to write a code which solves the reduced fractions problem seen online. 我正在尝试编写一个代码来解决在线看到的减少分数问题。 For small values of n and d I get an answer out, however when trying to solve for large values of n and d, the for loop takes so long that I get a memory error (after waiting for the code to run for about an hour). 对于n和d的小值,我得到了一个答案,但是当试图求解n和d的大值时,for循环需要很长时间才能得到内存错误(在等待代码运行大约一个小时之后) )。

"By listing the set of reduced proper fractions for d ≤ 1,000,000 in ascending order of size..." “通过按大小的升序列出d≤1,000,000的减少的适当分数集......”

Is there a way I can check all possible fractions for large values of n without using a lengthy for loop? 有没有办法可以在不使用冗长的for循环的情况下检查n的大值的所有可能分数?

fraction_list = []

for d in range(1000000):
    for n in range(1000000):
        if n<d and n/d ==0 :
            frac = float(n) / float(d)
            #print(frac)
            fraction_list.append(frac)



index_num = (fraction_list.index(float(2.0/7.0)))

sorted(fraction_list, key=float) 
print(fraction_list[index_num])
print("the fraction which is to the left is" + fraction_list[index_num -1])

I guess there may be more efficient methods than what I present here, but at least you can avoid the double loop when you realise that you don't need to calculate all factors with both numerator and denominator in the range of 0..1000000. 我想可能有比我在这里提出的方法更有效的方法,但是当你意识到你不需要计算分子和分母在0..1000000范围内的所有因子时,你至少可以避免双循环。

You could just do that loop on the denominator (starting at 1, not 0) only, and then increment the numerator (starting at 0) until it goes beyond the given fraction. 你可以只在分母(从1开始,而不是0)开始循环,然后递增分子(从0开始),直到它超出给定的分数。 At that moment decrement that numerator once, so it represents a potential candidate solution. 那时分子减去一次,所以它代表了一个潜在的候选解决方案。 Then in the next iteration -- when the denominator is one greater -- it is not necessary to reset the numerator to 0 again, it can continue where it left, as it is certain that the new fraction will be less than the given fraction: that is where you really gain time. 然后在下一次迭代中 - 当分母为1时,没有必要再次将分子重置为0,它可以在离开的地方继续,因为可以确定新分数将小于给定分数:那是你真正获得时间的地方。

This means you can use a linear method instead of quadratic: 这意味着您可以使用线性方法而不是二次方法:

def get_prev_fraction(num, denom, limit = 1000000):
    bestnum = 0
    bestdenom = 1
    a = 0
    for b in range(1,limit+1):
        while a*denom < b*num:
            a += 1
        a -= 1
        if a*bestdenom > b*bestnum:
            bestnum, bestdenom = a, b
    return bestnum, bestdenom


num, denom = get_prev_fraction(2, 7)

print("the fraction which is to the left of {}/{}={} is {}/{}={}".format(2, 7, 2.0/7, num, denom, num/denom))

This outputs: 这输出:

the fraction which is to the left of 2/7=0.2857142857142857 is 285713/999996=0.28571414285657143 在2/7 = 0.2857142857142857左侧的分数是285713/99996 = 0.28571414285657143

Note that the quote mentions d ≤ 1,000,000 , so you need to do range(1000001) to include that limit. 请注意,该帖提到d≤100万 ,所以你需要做的range(1000001)以包括限制。

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

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