Продолжение от дроби к дроби неисправности
Я работаю над Project Euler Problem 57 (Обожаю сайт!). Для этой задачи требуется преобразование между конечной дробной дробью и нормальной дробью. Я разработал алгоритм, который в основном принимает обратное значение последнего числа в списке, добавляет его к предпоследнему и продолжает до тех пор, пока не останется последняя дробь. Для задачи 67 это сработало некорректно, но на этот раз перестало работать после второй итерации (я должен выполнить алгоритм на нескольких непрерывных дробях).
Это кусок кода (я использовал внешний модуль, а именно sympy):
import time
from sympy import *
from sympy import fraction, Rational, Symbol
def cont_fract_to_fraction(cont_frac_list):
a=cont_frac_list[-1]
b=cont_frac_list[-2]
new_reduced=Rational(b,1)+ Rational(1,a)
cont_frac_list[-2]=new_reduced
del cont_frac_list[-1]
if len(cont_frac_list)==1:
print cont_frac_list #To check
return cont_frac_list
else:
cont_fract_to_fraction(cont_frac_list)
def numerator_higher_denominator(fraction):
num=str(fraction[0])
den=str(fraction[1])
if len(num)>len(den):
return 1
else:
return 0
start=time.time()
tally=0
for k in xrange (1, 101):
sqrt_eval=[1]
for x in xrange (1, k+2):
sqrt_eval.append(2)
sqrt_eval=cont_fract_to_fraction(sqrt_eval)
print sqrt_eval ##To double check
#fraction_result=fraction(soln[0]) To introduce later
#tally+=numerator_higher_denominator(fraction_result) To introduce later
elapsed=time.time()-start
print "Solution: ", tally, "Solved in: ", elapsed
Я в основном проверяю, чтобы увидеть, получает ли он всю конечную дробь, и печать из функции, до возврата, дает ответ, но печать после того, как я присвоил значение sqrt_eval, печатает None. Вот тестовый прогон:
###Test run#### [3/2] #--> function print [3/2] #--> sqrt_eval print [7/5] None [17/12] None [41/29] None [99/70] None [239/169] None [577/408] None [1393/985] None [3363/2378] None [8119/5741] None [19601/13860] None
Я тщательно искал ответ и не могу его найти. Помоги мне отладить это, если сможешь, не сильно меняя код.
2 ответа
Модуль фракций быстро решает эту проблему:
>>> from fractions import Fraction
>>> def normal_fraction(continued_fraction):
n = Fraction(0)
for d in continued_fraction[:0:-1]:
n = 1 / (d + n)
return continued_fraction[0] + n
>>> cf = [3,7,15,1,292,1,1,1,2,1,3,1]
>>> normal_fraction(cf)
Fraction(5419351, 1725033)
>>> float(_)
3.1415926535898153
Если вам нравится функциональное программирование и лаконичный код, приведенную выше логику можно выразить в виде одной строки с помощью метода Reduce ():
>>> cf[0] + reduce(lambda d, n: 1 / (d + n), cf[:0:-1], Fraction(0))
Fraction(5419351, 1725033)
А вот версия, которая не использует фракцию. Это будет работать даже на очень старых версиях Python:
def normal_fraction(continued_fraction):
n, d = 0, 1
for a in continued_fraction[:0:-1]:
n, d = d, a*d + n
return continued_fraction[0]*d + n, d
Это не отвечает на ваш вопрос, но в Википедии есть некоторые формулы, которые могут позволить вам вычислить это более эффективно.