import numpy class Polynomial: def __init__(self, coefficients): self.coeff = coefficients def __call__(self, x): """Evaluate the polynomial.""" s = 0 for i in range(len(self.coeff)): s += self.coeff[i]*x**i return s def __add__(self, other): """Return self + other as Polynomial object.""" # Two cases: # # self: X X X X X X X # other: X X X # # or: # # self: X X X X X # other: X X X X X X X X # Start with the longest list and add in the other if len(self.coeff) > len(other.coeff): result_coeff = self.coeff[:] # copy! for i in range(len(other.coeff)): result_coeff[i] += other.coeff[i] else: result_coeff = other.coeff[:] # copy! for i in range(len(self.coeff)): result_coeff[i] += self.coeff[i] return Polynomial(result_coeff) def __mul__(self, other): c = self.coeff d = other.coeff M = len(c) - 1 N = len(d) - 1 result_coeff = numpy.zeros(M+N+1) for i in range(0, M+1): for j in range(0, N+1): result_coeff[i+j] += c[i]*d[j] return Polynomial(result_coeff) def differentiate(self): """Differentiate this polynomial in-place.""" for i in range(1, len(self.coeff)): self.coeff[i-1] = i*self.coeff[i] del self.coeff[-1] def derivative(self): """Copy this polynomial and return its derivative.""" dpdx = Polynomial(self.coeff[:]) # make a copy dpdx.differentiate() return dpdx def __str__(self): s = '' for i in range(0, len(self.coeff)): if self.coeff[i] != 0: s += ' + %g*x^%d' % (self.coeff[i], i) # Fix layout s = s.replace('+ -', '- ') s = s.replace('x^0', '1') s = s.replace(' 1*', ' ') s = s.replace('x^1 ', 'x ') #s = s.replace('x^1', 'x') # will replace x^100 by x^00 if s[0:3] == ' + ': # remove initial + s = s[3:] if s[0:3] == ' - ': # fix spaces for initial - s = '-' + s[3:] return s def simplestr(self): s = '' for i in range(0, len(self.coeff)): s += ' + %g*x^%d' % (self.coeff[i], i) return s class Parabola(Polynomial): def __init__(self,c0,c1,c2): coeff = [c0,c1,c2] Polynomial.__init__(self,coeff) class Line(Parabola): def __init__(self,c0,c1): coeff = [c0,c1] Polynomial.__init__(self,coeff) #example usage p1 = Parabola(1,1,1) #1+x+x^2 p2 = Parabola(0,1,3) #x+3x^2 #Parabola inherits the __add__ method: print(p1+p2) #We can add a Line and a Parabola, since they are both #Polynomials (and therefore have the __add__ method) l1 = Line(2,1) #2+x print(l1+p1) #print the type (Line and Parabola): print(type(p1),type(l1)) """ Here we see that __add__ always returns a Polynomial object, as we see in the return value of the function. If we want addition of two Parabola to result in a Parabola object we need to reimplement __add__ in the Parabola class. """ print(type(p1+p2),type(l1+p2)) """Terminal >python Polynomial_hier.py 1 + 2*x + 4*x^2 3*1 + 2*x + x^2 """ def test_Polynomial(): p1 = Polynomial([1, -1]) p2 = Polynomial([0, 1, 0, 0, -6, -1]) p3 = p1 + p2 p3_exact = Polynomial([1, 0, 0, 0, -6, -1]) msg = 'p1 = %s, p2 = %s\np3=p1+p2 = %s\nbut wrong p3 = %s'%\ (p1, p2, p3_exact, p3) assert p3.coeff == p3_exact.coeff, msg # Note __add__ applies lists only, here with integers, so # == for comparing lists is not subject to round-off errors p4 = p1*p2 # p4.coeff becomes a numpy array, see __mul__ p4_exact = Polynomial(numpy.array([0, 1, -1, 0, -6, 5, 1])) msg = 'p1 = %s, p2 = %s\np4=p1*p2 = %s\ngot wrong p4 = %s'%\ (p1, p2, p4_exact, p4) assert numpy.allclose(p4.coeff, p4_exact.coeff, rtol=1E-14), msg p5 = p2.derivative() p5_exact = Polynomial([1, 0, 0, -24, -5]) msg = 'p2 = %s\np5 = p2.derivative() = %s\ngot wrong p5 = %s'%\ (p2, p5_exact, p5) assert p5.coeff == p5_exact.coeff, msg p6 = Polynomial([0, 1, 0, 0, -6, -1]) # p2 p6.differentiate() p6_exact = p5_exact msg = 'p6 = %s\p6.differentiate() = %s\ngot wrong p6 = %s'%\ (p2, p6_exact, p6) assert p6.coeff == p6_exact.coeff, msg if __name__ == '__main__': import sys if len(sys.argv) >= 2 and sys.argv[1] == 'verify': test_Polynomial()