Как на Python обеспечить вывод корней уравнения списком (вопрос о генераторах и модуле timeit)?
Реализую функцию нахождения корней методом дихотомии. Не стану здесь объяснять его суть - код реализован, причем достаточно корректно. Однако вот в чем загвоздка.
Функция dichotomy() содержит логику расчета корней уравнения, и мне надо получить их вывод в удобочитаемом виде. Сейчас когда ставлю print(root), я получаю вывод в столбик. Мне же требуется списком в строку, причем с нужным количеством цифр после запятой.
По отдельности это реализовано:
import numpy as np
import timeit
start_time = time.time()
res = list(dichotomy(0.0001,184,10000, 0.000001)) # написанная нами функция с заданными пользователем аргументами
print('Корни по методу дихотомии находятся в точках:')
print(', '.join(map(lambda x: f'{x:.4f}', res)))
print(f'Время счета по модулю timeit: ', timeit.timeit('dichotomy(0.0001,184,10000, 0.000001)', 'from __main__ import dichotomy'), 'seconds')
Однако занести код вывода в тело функции не получается. Это первая трудность.
Вторая: если объявляю время счета timeit.timeit() вне функции, то метод работает, внутри - уже нет. В общем сейчас этот код дает сбои в финальных строках:
import numpy as np
import timeit
def f(x):
return 1.2-np.log(x)-4*np.cos(2*x)
def dichotomy (a,b,n, eps): # отрезок от a до b делим на n частей, погрешность eps
"""
Функция отделения и уточнения корня
"""
assert a!=0, 'a равно 0'
assert b!=0, 'b равно 0'
# сначала отделим корни
grid=np.linspace(a, b, n)
# далее уточним корни
for x,y in zip(grid, grid[1:]):
if f(x) * f(y) > 0:
continue
root = None
while ( abs(f(y)-f(x)) )>eps:
mid = (y+x)/2
if f(mid) == 0 or f(mid)<eps:
root = mid
break
elif (f(mid) * f(x)) < 0:
y = mid
else:
x = mid
if root:
yield root
# print(root) # дает вывод столбиком - неудобно, потому пробуем ниже:
res = list(root) # ОШИБКА здесь!
print(', '.join(map(lambda x: f'{x:.4f}', res)))
print(f'Время счета по модулю timeit: ', timeit.timeit('dichotomy(0.0001,184,10000, 0.000001)', 'from __main__ import dichotomy'), 'seconds')
print(list(dichotomy(0.0001,184,10000, 0.000001))) # здесь юзер пытается подставить в функцию значения своих аргументов и получить распечатку корней
На выходе сейчас ошибка с указанием на res = list(root):
TypeError: 'numpy.float64' object is not iterable
Ответы (1 шт):
Ну тут возможны разные варианты. Но если вы делаете именно генератор, то лучше выводить результат уже после работы генератора:
# получаем результат
res = list(dichotomy(0.0001,184,10000, 0.000001))
# выводим результат
print(', '.join(map(lambda x: f'{x:.4f}', res)))
А из генератора две строки после yield root просто уберите.
Если же вы хотите делать печать именно в генераторе, то будет не совсем красиво - придётся следить за запятыми, либо в конце будет лишняя запятая. Примерно можно сделать как-то так в конце функции:
if root:
yield root
print(f'{root:.4f}', end=', ')
print()
print(f'Время счета по модулю timeit: ', timeit.timeit('dichotomy(0.0001,184,10000, 0.000001)', 'from __main__ import dichotomy'), 'seconds')