#----------------------------------------------------------------------
# Program to encode and explore polynomials in Python
#
# Copyright (C) December 6, 2017 -- Dr. William T. Verts
#
# I want to use Python to represent polynomials
# such as 12X^4 - 3X^3 + 2X^2 + 5X - 3
#
# How do we approach the problem?
#
#
#
# ---------------------------------------------------------------------
# Possible Solution #1: [[12,4], [-3,3], [2,2], [5,1], [-3,0]]
# ---------------------------------------------------------------------
# This solution works well if there are a few coefficients from terms
# with huge exponents. For example, 2X^1000000 - 3X^2000 + 5 would
# be represented by [[2,1000000], [-3,2000], [5,0]]
#
#
#
# ---------------------------------------------------------------------
# Possible Solution #2: Coefficients = [12,-3,2,5,-3]
# Exponents = [4,3,2,1,0]
# ---------------------------------------------------------------------
# This is essentially the same as Solution #1, but uses two lists of
# items instead of one list of two-item lists. For the earlier
# example, we would build the lists as follows:
# Coefficients = [2, -3, 5]
# Exponents = [1000000, 2000, 0]
#
#
#
# ---------------------------------------------------------------------
# Possible Solution #3: [-3, 5, 2, -3, 12]
# Where the index indicates the power
# ---------------------------------------------------------------------
# This is a far more elegant solution than either of the previous
# approaches in that the index into the list is the exponent of the
# corresponding term. It is compact and can support a lot of terms
# efficiently, BUT it doesn't handle our earlier example of a poly with
# very large exponents gracefully at all. However, this is the
# method we'll use here.
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# Evaluate polynomial P at X. For example, evaluating the polynomial
# 5X^3 - 2X^2 + 4X + 1 at X=2.5 would be coded as:
# polyEvaluate([1,4,-2,5], 2.5)
#----------------------------------------------------------------------
def polyEvaluate (P, X):
Result = 0
Power = 1
for Coefficient in P:
Result = Result + Coefficient * Power
Power = Power * X
return Result
#----------------------------------------------------------------------
# Generate a mathematical representation of a polynomial. The HTML
# parameter controls whether the result is appropriate for display in
# a Web browser, or just for normal text. For example:
#
# polyStr([1,4,-2,5], False) returns '5X^3 - 2X^2 + 4X + 1'
#
# polyStr([1,4,-2,5) also returns '5X^3 - 2X^2 + 4X + 1'
#
# polyStr([1,4,-2,5], True) returns
# '5x3 - 2x2 + 4x + 1'
#----------------------------------------------------------------------
def polyStr (P, HTML=False):
S = ""
for Exponent in range(len(P)-1,-1,-1):
Coefficient = P[Exponent]
if (Coefficient != 0):
if (Coefficient < 0):
if (S != ""):
S = S + " - "
else:
S = S + "-"
else:
if (S != ""):
S = S + " + "
if (Exponent == 0) or (abs(Coefficient) != 1):
S = S + str(abs(Coefficient))
if (Exponent >= 1):
if HTML:
S = S + "x"
else:
S = S + "X"
if (Exponent > 1):
if HTML:
S = S + "" + str(Exponent) + ""
else:
S = S + "^" + str(Exponent)
if (S == ""): S = "0"
return S
#----------------------------------------------------------------------
# Return a polynomial equivalent to P except that leading terms with
# zero coefficients are suppressed, and any float terms with fractions
# equal to (or nearly equal to) zero are changed to ints.
# Note that this function uses a slightly different method than in the
# Companion. P is copied to Q so that changes to Q do not affect the
# variable passed in as P.
#----------------------------------------------------------------------
import copy
def polyNormalize (P):
Q = copy.deepcopy(P)
for I in range(len(Q)):
if ((abs(Q[I]) - float(int(abs(Q[I])))) <= 1.0E-14):
Q[I] = int(Q[I])
while (len(Q) > 1) and (Q[-1] == 0): del Q[-1]
return Q
#----------------------------------------------------------------------
# Add two or three polynomials. Notice that enough space is allocated
# in Result for the largest polynomial, each polynomial is added to
# the result dependent on its length, and the result is normalized
# before return. If P2 is omitted, its length will be zero, and the
# third for-loop won't do anything.
#----------------------------------------------------------------------
def polyAdd (P0,P1,P2=[]):
Result = [0] * max(len(P0),len(P1),len(P2))
for I in range(len(P0)): Result[I] = Result[I] + P0[I]
for I in range(len(P1)): Result[I] = Result[I] + P1[I]
for I in range(len(P2)): Result[I] = Result[I] + P2[I]
return polyNormalize(Result)
#----------------------------------------------------------------------
# Subtract one polynomial from another. The technique is similar to
# that of polyAdd.
#----------------------------------------------------------------------
def polySubtract (P0,P1):
Result = [0] * max(len(P0),len(P1))
for I in range(len(P0)): Result[I] = Result[I] + P0[I]
for I in range(len(P1)): Result[I] = Result[I] - P1[I]
return polyNormalize(Result)
#----------------------------------------------------------------------
# Can you fill these in?
#----------------------------------------------------------------------
def polyMultiply (P0,P1):
# Complicated but not too bad.
# Fairly easy to implement.
return polyNormalize(Result)
def polyDivide (P0,P1):
# Much ugliness.
# Such computation.
# Wow.
return polyNormalize(Result)
def polyDifferentiate (P):
# Surprisingly easy to compute d/dx(P)
return polyNormalize(Result)
def polyIntegrate (P,C=0):
# Surprisingly easy to compute Integral(P) + C
return polyNormalize(Result)