#------------------------------------------------------------
# Copyright (C) 2017-2019 Dr. William T. Verts
#------------------------------------------------------------
# See pages 272-275 in the Companion for a variation of
# these functions
#------------------------------------------------------------
#------------------------------------------------------------
# Clean up a polynomial by enforcing the following rules:
#
# (1) The polynomial is never empty.
# (2) Any floats with fractions really close to zero
# get converted to integers.
# (3) Any high-order coefficients of zero get deleted,
# except that if the polynomial is entirely zeroes
# the result returned is [0].
# Examples:
# polyNormalize([2,0,3,4,0,5]) returns [2,0,3,4,0,5]
# polyNormalize([2,0,3,0,0,0]) returns [2,0,3]
# polyNormalize([2.0, 3.5, 4]) returns [2, 3.5, 4]
# polyNormalize([0,0,0,0,0,0]) returns [0]
# polyNormalize([]) returns [0]
#------------------------------------------------------------
def polyNormalize (P): # P is a list of coefficients
Q = [0 for I in range(max(1,len(P)))] # Create a zero polynomial Q the same size as P (or [0] if P==[])
for I in range(len(P)): # For every entry in P
Value = P[I] # Grab the coefficient
if (abs(Value - float(int(Value))) < 1.0E-14): # Close enough to integer to call it one
Q[I] = int(Value) # Convert (possible) float to int
else: #
Q[I] = Value # Have to keep it as a float
while (len(Q) > 1) and (Q[-1] == 0): del Q[-1] # Delete any high-order zero entries (but leave one if all were 0)
return Q # Return the cleaned-up polynomial equivalent to P
#------------------------------------------------------------
# Add/Subtract two or three polynomials.
#------------------------------------------------------------
def polyAdd(P0,P1,P2=[]): # P0, P1, and P2 are lists of coefficients
P = [0 for I in range(max(len(P0),len(P1),len(P2)))] # P will be my answer, length assumed to be same as longest polynomial
for I in range(len(P0)): P[I] = P[I] + P0[I] # Add P0 to result
for I in range(len(P1)): P[I] = P[I] + P1[I] # Add P1 to result
for I in range(len(P2)): P[I] = P[I] + P2[I] # Add P2 to result
return polyNormalize(P) # Return cleaned-up result
def polySubtract(P0,P1,P2=[]): # P0, P1, and P2 are lists of coefficients
P = [0 for I in range(max(len(P0),len(P1),len(P2)))] # P will be my answer, length assumed to be same as longest polynomial
for I in range(len(P0)): P[I] = P[I] + P0[I] # Add P0 to result
for I in range(len(P1)): P[I] = P[I] - P1[I] # Subtract P1 from result
for I in range(len(P2)): P[I] = P[I] - P2[I] # Subtract P2 from result
return polyNormalize(P) # Return cleaned-up result
#------------------------------------------------------------
# Multiply two polynomials. This is like multiplying two
# large numbers by hand where there are partial products
# that must be added to the correct digit position. In this
# case, the position of a partial product is determined by
# the new exponent. For example, if P0 = [1,4,2] = 2X^2+4X+1
# and P1 = [7,3,8] = 8X^2+3X+7, then the partial product of
# P0[1] and P1[2] represents the 4X term times the 8X^2 term,
# which is 32X^3, so result of multiplying P0[1] and P1[2]
# (the 32) adds into slot 1+2 of the result, or P[3]. That
# is, if I=1 and J=2, then P[I+J] = P[I+J] + P0[I] * P1[J]
# is the same as P[3] = P[3] + P0[1] * P1[2].
#------------------------------------------------------------
def polyMultiply(P0,P1): # P0 and P1 are lists of coefficients
P = [0 for I in range(len(P0)+len(P1))] # P will be my answer, length assumed to be total of terms in both polynomials
for I in range(len(P0)): # Step through all coefficients in P0,
for J in range(len(P1)): # For each coefficient in P0 step through all coefficients in P1,
P[I+J] = P[I+J] + P0[I] * P1[J] # Add partial product to correct slot in the answer
return polyNormalize(P) # Return cleaned-up result
#------------------------------------------------------------
# Differentiate P(X) with respect to X. In this code the
# P[0] term is the constant, which is ignored, and the result
# will have one fewer terms than the source. All other terms
# multiply the exponent (I) times the coefficient (P[I]) to
# get the coefficient of the next lower term. Notice that
# the code to differentiate a polynomial is significantly
# smaller and simpler than multiplication!
#------------------------------------------------------------
def polyDifferentiate(P):
Q = [0 for I in range(len(P)-1)]
for I in range(1,len(P)): Q[I-1] = I * P[I]
return polyNormalize(Q)
#------------------------------------------------------------
# Convert a polynomial from its internal representation into
# a string that has the appearance of a standard mathematical
# polynomial. That is, a polynomial such as [-1, 2, 0, 5]
# returns the string 5X^3 + 2X - 1 (notice that the X^1 term
# suppresses the exponent, the X^0 term uses just the
# coefficient, and the X^2 term has a zero coefficient and
# is therefore ignored).
#------------------------------------------------------------
def polyStr(P):
S = ""
for Exponent in range(len(P)-1,-1,-1): # Step through coefficients from highest exponent to lowest
Coefficient = P[Exponent]
if Coefficient != 0: # We only care about non-zero coefficients
if Coefficient < 0:
if S != "":
S = S + " - " # String not empty and coefficient was negative (internal term)
else:
S = S + "-" # String was empty but coefficient was negative (first term)
else:
if S != "":
S = S + " + " # String not empty and coefficient was positive (internal term)
# The + is suppressed if first term was positive.
if (Exponent == 0) or (abs(Coefficient) != 1): # No need to include coefficient if it is 1 (unless it's the X^0 term)
S = S + str(abs(Coefficient)) # Include the coefficient without a sign (handled earlier)
if (Exponent >= 1): # Include X for all but the X^0 term
S = S + "X"
if (Exponent > 1): # Include the exponent for all terms X^2, X^3, X^4, etc., but not X^0 or X^1
S = S + "^" + str(Exponent)
if S == "": S = "0" # If the string comes up empty, it's zero.
return S
#------------------------------------------------------------
# Tests
#------------------------------------------------------------
Frog = [-1,7,0.5,0,-3]
Toad = [5,-3,2.5,2,-3]
print ("Frog = " + polyStr(Frog))
print ("Toad = " + polyStr(Toad))
print ("Frog + Toad = " + polyStr(polyAdd(Frog,Toad)))
print ("Frog - Toad = " + polyStr(polySubtract(Frog,Toad)))
print ("Frog * Toad = " + polyStr(polyMultiply(Frog,Toad)))
print ("d/dx(Frog) = " + polyStr(polyDifferentiate(Frog)))