Python Forum

Full Version: Generating a polynomial equation
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am new at Python and I found that the best way to learn is to practice. So I decided to write a program that involves generating a polynomial equation from inputting the degree of the polynomial and the corresponding coefficients. For example:

degree = 4
coefficients = 3, 8, 6, 9, and 2

These values should afford the following polynomial equation:

y = 2x^4 + 9x^3 + 6x^2 + 8x^1 + 3x^0

At first, this seemed like an easy task, but I came to a dead end. Angry Any ideas?
Definitely, you need to create a class Polynom. Instances of that class will be polynomials. Further, you can override arithmetic operations to be able to add two polynomials, multiply polynomials each other etc.
As a starting point, I just wrote some code defining Polynom class.

import sys
import types
from numbers import Number
from abc import ABCMeta, abstractmethod
from collections.abc import Sequence
from itertools import zip_longest


class PolynomBase(metaclass=ABCMeta):
    eps = sys.float_info.epsilon
    
    def __init__(self, coefficients):
        """Initialize a polynom"""

        if isinstance(coefficients, Sequence):
            self.coefficients = tuple(coefficients)
            if not all(map(lambda x: isinstance(x, Number), self.coefficients)):
                raise Exception("Array of coefficients should contain numbers only.")
            if len(self.coefficients) == 0:
                raise Exception("Length of the array of coefficients is zero.")
            if all(map(lambda x: abs(x) < self.eps , self.coefficients)):
                raise Exception("At least one coefficient of the polynom should be greater than eps = {}".format(eps))
        else:
            raise Exception("Array of coeffcients should be of sequence type")
    
    def __repr__(self):
        """Official representation of the polynomial object"""
        return self.__str__()

    def __str__(self):
        """Polynom pretty printing"""
        return ' + '.join("{}x^{}".format(c, i) for i, c in enumerate(self.coefficients))
    
    @abstractmethod
    def calculate(self, x):
        """Returns value of P(x)"""

    @abstractmethod
    def __add__(self, other):
        """Polynom addition"""

#     @abstractmethod
#     def __sub__(self, other):
#         """Polynom substraction"""

#     @abstractmethod
#     def __mul__(self, other):
#         """Polynom multiplication"""

    def __len__(self):
        return self.degree + 1

    @property
    @abstractmethod
    def degree(self):
        """Returns degree of a polynom"""


class Polynom(PolynomBase):
    
    def __init__(self, coefficients):
        super().__init__(coefficients)
    
    def __add__(self, other):
        if isinstance(other, PolynomBase):
            coefficients = []
            for a, b in zip_longest(self.coefficients, other.coefficients, fillvalue=0.0):
                coefficients.append(a + b)
            return Polynom(coefficients)
        elif isinstance(other, Number):
            coefficients = list(self.coefficients)
            coefficients[0] += other
            return Polynom(coefficients)
        raise Exception("Could not add an object of {} to an object of {}".format(type(self), type(other)))

    def __radd__(self, other):
        return self.__add__(other)

    def calculate(self, x):
        res = 0.0
        for p, j in enumerate(self.coefficients):
            res += j * x ** p
        return res
        
    @property
    def degree(self):
        return len(self.coefficients) - 1

    # you need to define additional methods here.
p = Polynom((1,2,3))
print(p)
Output:
1*x^0 + 2*x^1 + 3*x^2
p + 3
Output:
4*x^0 + 2*x^1 + 3*x^2
Thanks for your detailed response. I am just beginning to learn about classes and find that they are somewhat abstract. I still don't have a good grasp on the topic; everything that I learned thus far has been smooth sailing.
You can describe polynomial without classes. Any polynomial is defined by its coefficients, so standard data types such as tuple or list can describe a polynomial.

my_polynomial = (1, 2, 3) # we assume that we have a polynomial:  1*x^0 + 2*x + 3*x^2
Further, we need some helper functions that will allow to perform basic operations over such polynomials.

We wish to print the polynomial in human readable form:

def print_polynomial(p, default_argument_name='x'):
    """Print polynomial

    p: a list or a tuple, polynomial coefficients
    """
    result = ''
    for power, coefficient in enumerate(p):
        result += '{}*{}^{} +'.format(coefficient, default_argument_name, power)
    # This is dirty implementation, it doesn't handle +/- signs properly
    print(result[:-1])  # drop `+`
Also, we would like to calculate value of the polynomial at specified point. So, we need to define
a function, e.g. get_polynomial_value,

def get_polynomial_value(p, x):
    """Evaluates polynomial at specified point
    """
    result = 0.0
    for power, coefficient in enumerate(p):
        result += coefficient * x ** power
    return result
You can also wish to be able to export polynomial to Tex/LaTex-format. Thats easy, just write a helper function for this.

def export_to_latex(p):
    """Returns latex-formatted representation of a polynomial"""
    result = r""
    for power, coefficient in enumerate(p):
        result += r'{coefficient}\cdot x^{}'.format(coefficient, power) + '+' if (power != len(coefficient)) else '' # drop `+` for the last polynomial term
    return result
I didn't test these function. You can definitely improve them (e.g. an issue with +/- handling when printing a polynomial), define you own help functions, e.g. define add_polynomials(p1, p2), multiply_polynomials(p1,p1) etc.