3

I'm trying to write a function that takes as input a list of coefficients (a0, a1, a2, a3.....a n) of a polynomial p(x) and the value x. The function will return p(x), which is the value of the polynomial when evaluated at x.

A polynomial of degree n with coefficient a0, a1, a2, a3........an is the function

p(x)= a0+a1*x+a2*x^2+a3*x^3+.....+an*x^n

So I'm not sure how to attack the problem. I'm thinking that I will need a range but how can I make it so that it can handle any numerical input for x? I'm not expecting you guys to give the answer, I'm just in need of a little kick start. Do I need a for loop, while loop or could recursive be an option here?

def poly(lst, x)

I need to iterate over the items in the list, do I use the indices for that, but how can I make it iterate over an unknown number of items?

I'm thinking I can use recursion here:

    def poly(lst, x):
        n = len(lst)
        If n==4:
           return lst[o]+lst[1]*x+lst[2]*x**2+lst[3]*x**3
        elif n==3:
           return lst[o]+lst[1]*x+lst[2]*x**2
        elif n==2:
           return lst[o]+lst[1]*x
        elif n==1:
           return lst[o]
        else:
            return lst[o]+lst[1]*x+lst[2]*x**2+lst[3]*x**3+lst[n]*x**n

This works for n<=4 but I get a index error: list index out of range for n>4, can't see why though.

Snarre
  • 597
  • 5
  • 14
  • 22
  • 2
    Hint: look up what `sum` and `enumerate` do. (PS: Don't forget that in Python, we use `**` and not `^` for exponentiation, i.e. `x*x = x**2`.) – DSM Jun 04 '13 at 21:01
  • I know what sum does, but what throws me off is how to write the code so that the n value is incorporated – Snarre Jun 04 '13 at 21:11
  • @Snarre Check out my answer, I think that is what you wanted. – Rushy Panchal Jun 04 '13 at 21:12
  • `enumerate` is there for you. Look up what it does. It should help you in creating the n for each coefficient. – Sukrit Kalra Jun 04 '13 at 21:12
  • @Answerers: Since OP asks for *any numerical input* depending on `x` and the coefficients one might want to use an adjusted ordering when doing the sum to avoid loosing too much precision. – Benjamin Bannier Jun 04 '13 at 21:38

5 Answers5

9

The most efficient way is to evaluate the polynomial backwards using Horner's Rule. Very easy to do in Python:

# Evaluate a polynomial in reverse order using Horner's Rule,
# for example: a3*x^3+a2*x^2+a1*x+a0 = ((a3*x+a2)x+a1)x+a0
def poly(lst, x):
    total = 0
    for a in reversed(lst):
        total = total*x+a
    return total
JCF
  • 91
  • 1
  • 1
2
def evalPoly(lst, x):
    total = 0
    for power, coeff in enumerate(lst): # starts at 0 by default
        total += (x**power) * coeff
    return total

Alternatively, you can use a list and then use sum:

def evalPoly(lst, x):
        total = []
        for power, coeff in enumerate(lst):
            total.append((x**power) * coeff)
        return sum(total)

Without enumerate:

def evalPoly(lst, x):
    total, power = 0, 0
    for coeff in lst:
        total += (x**power) * coeff
        power += 1
    return total

Alternative to non-enumerate method:

def evalPoly(lst, x):
    total = 0
    for power in range(len(lst)):
        total += (x**power) * lst[power] # lst[power] is the coefficient
    return total

Also @DSM stated, you can put this together in a single line:

def evalPoly(lst, x):
    return sum((x**power) * coeff for power, coeff in enumerate(lst))

Or, using lambda:

evalPoly = lambda lst, x: sum((x**power) * coeff for power, coeff in enumerate(lst))

Recursive solution:

def evalPoly(lst, x, power = 0):
    if power == len(lst): return (x**power) * lst[power]
    return ((x**power) * lst[power]) + evalPoly(lst, x, power + 1)

enumerate(iterable, start) is a generator expression (so it uses yield instead of return that yields a number and then an element of the iterable. The number is equivalent to the index of the element + start.

From the Python docs, it is also the same as:

def enumerate(sequence, start=0):
    n = start
    for elem in sequence:
        yield n, elem
        n += 1
Rushy Panchal
  • 16,979
  • 16
  • 61
  • 94
  • Yeah it works but we haven't covered enumerate in class so I'm not sure why or how it works. – Snarre Jun 04 '13 at 21:16
  • (1) I don't think you want to start at 1. The OP's first term is `a0*x**0`. (2) We could compress the entire thing to `sum(coeff*x**i for i, coeff in enumerate(lst))`. – DSM Jun 04 '13 at 21:20
  • @DSM I was thinking of putting it as a one-liner, but thought that might be confusing. But I'll add it in anyway :). – Rushy Panchal Jun 04 '13 at 21:21
  • Well since we haven't used enumerate or lambda in class yet I think I need to stick with indices. But what confuses me is where is the function p(x)= a0+a1*x+a2*x^2+a3*x^3+.....+an*x^n in your code guys? – Snarre Jun 04 '13 at 21:27
  • @Snarre That comes from the `for` loop. `for power, coeff in enumerate(lst)` would start off with 0, a0. Then, the next would be 1, a1. a0 and a1 are the coefficients provided in `lst`, and 0 and 1 are the powers provided by the `enumerate` function. – Rushy Panchal Jun 04 '13 at 21:43
  • @Snarre Check out my new edit. `for coeff in lst` provides the coefficient from the list (which is given by the user) and `power` is just a variable that you increment. – Rushy Panchal Jun 04 '13 at 21:52
  • not necessarily recursive; it's more brute-force. It's not the best way, because you don't know how many exponents are going to be in the list. – Rushy Panchal Jun 04 '13 at 22:37
2

simple:

def poly(lst, x): 
  n, tmp = 0, 0
  for a in lst:
    tmp = tmp + (a * (x**n))
    n += 1

  return tmp

print poly([1,2,3], 2)

simple recursion:

def poly(lst, x, i = 0):
  try:
    tmp = lst.pop(0)
  except IndexError:
    return 0
  return tmp * (x ** (i)) + poly(lst, x, i+1)

print poly([1,2,3], 2)
Yura Beznos
  • 546
  • 4
  • 9
1

Either with recursion, or without, the essence of the solution is to create a loop on "n", because the polynomial starts at x^0 and goes up to a_n.x^n and that's the variable you should also consider as an input. Besides that, use a trick called multiply and accumulate to be able to calculate partial results on each loop iteration.

hdante
  • 7,685
  • 3
  • 31
  • 36
0
def evalPoly(lst, x, power):
    if power == 0:
        return lst[power]
    return ((x**power) * lst[power]) + evalPoly(lst, x, power - 1)

lst = [7, 1, 2, 3]
x = 5
print(evalPoly(lst, x, 3))

Equation to evaluate is - 3x^3 + 2x^2 + x + 7 when x = 5, result is - 437