#---------------------------------------------------------------------- # 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)