На этом шаге мы рассмотрим рекурсивную реализацию этой схемы.
Цель этой задачи - вычислить полином степени n:
P(x) = cnxn + cn-1xn-1 + ... + c1x + c0 (4.5)
P(x) = с0 + x(c1 + x(c2 + ... + x(cn-1 + cnx))).
Ясно, что размер задачи - это степень n полинома. Таким образом, начальное условие выполняется при n = 0 с очевидным результатом 0. На практике коэффициенты c должны быть определяющим полином списком (или похожей структурой данных вроде массива) из n + 1 элементов. Поэтому начальное условие достигается, когда длина этого списка равна 1.
Чтобы воспользоваться рекурсией, нужно найти подзадачу меньшего размера, подобную исходной. Декомпозиция задачи с уменьшением ее размера на 1:
полная задача ┎---------------------------------------------┑ P(x) = с0 + x(c1 + x(c2 + ... + x(cn-1 + cnx))). ┕---------------------------------------┙ подзадача
Если пренебречь коэффициентом c0 и первым умножением на x, то получающаяся подзадача имеет точно такую же структуру, как у исходной задачи. Если p(c, x) - функция, вычисляющая заданный своими коэффициентами c полином от x, то рекурсивная формула будет такой:
p(c, x) = c0 + x * p(c1...n, x),
c0, если n = 1, p(c, x) = с0 + х * p(c1...n, х), если n > 1,
1 2 3 4 5 |
def horner(c, x): if len(c) == 1: return c[0] else: return c[0] + x * horner(c[1:], x) |
Важно отметить, что уменьшение размера задачи, начиная с cn вместо c0, не приводит к схеме Горнера. В этом случае рекурсивная формула была бы такой:
p(c, x) = p(c0...n-1, x) + cnxn,
На следующем шаге мы рассмотрим треугольник Паскаля.