Albion College

CS 171

Introduction to Computer Science I & Lab

Fall 2021

Lab 10: Polynomials

In this lab you will familiarize yourself with classes and lists by working with a class which supports polynomial functions.

Polynomial functions

A polynomial \(p\) is a function of the form \[ \begin{align} p(x) &= a_nx^n + a_{n-1}x^{n-1} + \cdots + a_i x^i + \cdots + a_2 x^2 + a_1 x + a_0 \\ &= \underbrace{a_0 + a_1 x + a_2 x^2 + \cdots + a_i x^i + \cdots + a_{n-1}x^{n-1} +a_nx^n}_{(n+1) \text{ terms}} \\ &= \sum_{i=0}^n a_i x^i \quad(\text{recall } x^0 = 1) \end{align} \] where the values \(a_0\), \(a_1\), \(\ldots\), \(a_n \ne 0\) are constants called the coefficients of \(p\), with \(a_i\) being the \(i\)th coefficient. Here we will assume the constants are real numbers, but they could be complex numbers or other mathematical entities. The degree of \(p\) is \(n\).

The zero polynomial is just \(p(x) = 0\) and its degree is undefined (or sometimes -1).

Negating a polynomial multiplies all coefficients by -1. \[\begin{align} -p(x) &= -a_0 + -a_1 x + -a_2 x^2 + \cdots + -a_i x^i + \cdots + -a_{n-1}x^{n-1} + -a_nx^n \\ &= -a_0 - a_1 x - a_2 x^2 - \cdots - a_i x^i - \cdots - a_{n-1}x^{n-1} - a_nx^n. \end{align}\]

Mulitplying a polynomial by a constant \(b\) multiplies all coefficients by \(b\). \[\begin{align} b p(x) &= b a_0 + b a_1 x + b a_2 x^2 + \cdots + b a_i x^i + \cdots + b a_{n-1}x^{n-1} + b a_nx^n. \end{align}\]

In evaluating the a polynomial \(p\), you should try and be as efficient as possible. If you compute all the powers of \(x\) and don't save any intermediate results, that is not very efficient. Instead use an additional variable to store \(x^i\) and just multiply by \(x\) every pass of the loop. Another way is called Horner's method, which is related to synthetic division.

Given two polynomials p and q with degrees \(n\) and \(m\) respectively with \(n < m\). In reality the opposite may be the case or \(n\) and \(m\) could be equal. Thus \[p(x) = a_0 + a_1 x + a_2 x^2 + \cdots + a_i x^i + \cdots + a_{n-1}x^{n-1} + a_nx^n \] and \[q(x) = b_0 + b_1 x + b_2 x^2 + \cdots + b_i x^i + \cdots + b_{n-1}x^{n-1} + b_nx^n + \cdots + b_{m-1}x^{m-1} + b_mx^m. \] then \[ p(x) + q(x) = \underbrace{ \underbrace{ (a_0 + b_0) + (a_1 + b_1) x + (a_2 + b_2) x^2 + \cdots + (a_{n}+ b_{n}) x^{n}}_{(n+1) \text{ terms}} + b_{n+1} x^{n+1} + \cdots + b_{m-1}x^{m-1} + b_mx^m.}_{(m+1) \text{ terms}} \] Multiplying two polynomials is more challenging. \[ r(x) = p(x)q(x) = a_0 x^0 q(x) + a_1 x^1 q(x) + \cdots + a_n x^n q(x) \] Note that the resulting polynomial \(r\) has degree \(N = m+n\) with \(c_i\) being the \(i\)th coefficient of \(r\), which results from adding all \(a_j\) and \(b_k\) such that \(i = j+k\), so \[c_i = a_0 b_i + a_1 b_{i-1} + \cdots + a_{i-1} b_1 + a_i b_0 = \sum_{j = 0}^i a_j b_{(i-j)}.\] You will need two nested loops for this.

The derivative of a polynomial, denoted \(p'(x)\) is given by \[p'(x) = a_1 + 2 a_2 x + 3 a_3 x^2 + \cdots + i a_i x^{i-1} + \cdots + n a_n x^{n-1} = \sum_{i=1}^{n} i a_{i} x^{i-1}.\] This new polynomial has degree \(n-1\). Note the limits on the summation.

The indefinite integral of a polynomial, denoted by P(x) or \(\int p(x)\,dx\), is given by \[P(x) = \int p(x)\,dx = C + a_0 x + \dfrac{a_1}{2} x^2 + \dfrac{a_2}{3} x^3 + \cdots + \dfrac{a_{i-1}}{i} x^{i} + \cdots + \dfrac{a_{n}}{n+1} x^{n+1} = C + \sum_{i=1}^{n+1} \dfrac{a_{i-1}}{i} x^{i}. \] This new polynomial has degree \(n+1\). In our case we are assuming \(C = 0\). Note the limits on the summation.

The definite integral of the function \(p\) from \(x_1\) to \(x_2\) , is given by \[\int_{x_1}^{x_2} p(x)\,dx = P(x_2) - P(x_1) \] where \(P(x)\) is the indefinite integral defined above.

Task

Complete the methods in Polynomial.py, as shown below. After you complete each method, demonstrate it to your instructor. Change the driver/navigator roles after each method.

Polynomial.java

# CS 171 - Lab 10 # YOUR NAMES AND EMAILS HERE class Polynomial: def __init__(self, lst): self.a = [a for a in lst] def __str__(self): t = "" for i in range(len(self.a)-1, -1, -1): t += str(self.a[i]) if i==1: t += "x + " elif i != 0: t += "x^"+str(i)+" + " return t # return polynomial's degree (highest power of x) # a constant polynomial, such as p(x) = 5, has degree 0 def degree(self): return 0 # FIXME # return coefficient of x^i def coeff(self, i): return 0 # FIXME # return the polynomial evaluated at x def f(self, x): return 0 # FIXME # return the derivative polynomial p'(x) # create a new array of coefficients # then use that to create a new Polynomial def derivative(self): return Polynomial([0]) # FIXME # Use the power rule to integrate p(x), assume constant C is zero # create a new array of coefficients # then use that to create a new Polynomial def integrate(self): return Polynomial([0]) # FIXME # compute the definite integral of p(x) from x1 to x2 # use your integrate() method to compute P # then compute the difference of P(x2) and P(x1) def integral(self, x1, x2): return 0 # FIXME # add two polynomials # create a new array of coefficients # which polynomial has the largest degree? # then use that to create a new Polynomial def add(self, p): return Polynomial([0]) # FIXME # multiply two polynomials # create a new array of coefficients # then use that to create a new Polynomial def mul(self, p): return Polynomial([0]) # FIXME def main(): polys = list() polys.append(Polynomial([0.0])) # p(x) = 0 polys.append(Polynomial([1.0])) # p(x) = 1 polys.append(Polynomial([2.0, -1.0])) # p(x) = -x + 2 polys.append(Polynomial([6.0, 5.0, 1.0])) # p(x) = x^2 + 5x + 6 polys.append(Polynomial([1.0, 5.0, 7.0, 3.0])) # p(x) = 3x^3 + 7x^2 + 5x + 1 n = len(polys) for i in range(n): p = polys[i] p1 = polys[(i-1+n)%n] print("p(x) =", p) print("degree of p:", p.degree()) x = 0.0 print("p("+str(x)+") = "+str(p.f(x))+" =?", p.coeff(0)) x = 1.0 print("p("+str(x)+") = "+str(p.f(x))) x = -1.0 print("p("+str(x)+") = "+str(p.f(x))) x = 2.0 print("p("+str(x)+") = "+str(p.f(x))) print("coefficients: ", end="") for i in range(p.degree() + 1): print(p.coeff(i), end=" ") print() q = p.derivative() print("derivative: p'(x) =", q) print("degree of p':", q.degree()) q = p.integrate() print("integrate: P(x) =", q) print("degree of P:", q.degree()) r = q.derivative() print("derivative: P'(x) =", r, "=?", p) v = p.integral(1.0, 2.0) print("integral from 1.0 to 2.0 =", v) #r = Polynomial.add(p,p1) r = p.add(p1) print("("+str(p)+") + ("+str(p1)+") =", r) print("degree of r:", r.degree()) #r = Polynomial.mul(p,p1) r = p.mul(p1) print("("+str(p)+") * ("+str(p1)+") =", r) print("degree of r:", r.degree()) print("--------------------------------------------------------") main()

When you are finished, email your lab files to your lab partner and instructor.