简体   繁体   中英

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).

"By listing the set of reduced proper fractions for d ≤ 1,000,000 in ascending order of size..."

Is there a way I can check all possible fractions for large values of n without using a lengthy for loop?

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.

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. 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.

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

Note that the quote mentions d ≤ 1,000,000 , so you need to do range(1000001) to include that limit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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