El TDA Polinomio representa un polinomio con coeficientes reales, son mutables y residen en memoria dinámica.
El diseño de este TDA trata de buscar la eficiencia, ha prestado más atención a la eficiencia que a modelar el concepto exacto de polinomio, por ello, la mayoría de los operadores aritméticos, tienen efectos laterales (modificando al receptor) y devuelven referencias al objeto receptor (modificado), esto también explica que los objetos del TDA se definan como "mutables".
Dentro del TDA Polinomio hemos propuesto las siguientes primitivas :
· Polinomio ( ) -> construye el polinomio p(x) = 0.
· Polinomio (float * c, int g) -> construye un polinomio a partir de un vector de coeficientes, crea el polinomio : c[0] + c[1]*x + c[2] x2 + ... + c[g] xg.
PARÁMETROS : c -> vector de coeficientes, debe tener g+1 componentes.
g -> grado del polinomio que se quiere crear.
· Polinomio (const Polinomio & p) -> constructor de copia, que no comparte.
PARÁMETROS : p -> polinomio que se copia.
· Ostream & operator << (ostream & s, const Polinomio & p) -> sobrecargar el operador de extracción para polinomios, escribe 'p' sobre el flujo 's' con el formato Coef(Grado()) xGrado() + ... + Coef(1) x + Coef(0), presentando sólo los monomios con coeficiente distinto de 0.
PARÁMETROS : s -> flujo de salida, es modificado.
p -> polinomio que se escribe.
· Bool Nulo () const -> nos dice si el polinomio se puede considerar como nulo.
· Float Coef (int i) const -> obtiene un coeficiente, devuelve el coeficiente del monomio i-ésimo del receptor.
PARÁMETROS : i -> orden del coeficiente a obtener. i >= 0.
· Int Grado () const -> obtiene el grado del polinomio, devuelve el grado del receptor.
· Float operator () (float x) const -> evalúa el polinomio en un punto, devuelve la evaluación del receptor en x.
PARÁMETROS : x -> punto en que se evalúa el receptor.
· Bool operator == (const Polinomio & p) const -> comparación de igualdad, devuelve true, si el receptor y p son iguales. false, en otro caso.
PARÁMETROS : p -> polinomio con que se compara.
· Bool operator != (const Polinomio & p) const -> comparación de desigualdad, devuelve true, si el receptor y p son distintos. false, en otro caso.
PARÁMETROS : p -> polinomio con que se compara.
· Friend Polinomio &operator - (Polinomio & p) -> cambia el signo de los coeficientes de un polinomio, el polinomio p es cambiado por otro cuyos coeficientes resultan de invertir el signo a los de p.
POSTCONDICIÓN : el receptor es modificado
PARÁMETROS : p -> polinomio a invertir.
· Polinomio &operator + (const Polinomio & p) -> añade al receptor otro polinomio,al polinomio receptor se añade el polinomio p y el resultado se deja sobre el propio receptor.
POSTCONDICIÓN : el receptor es modificado
PARÁMETROS : p -> polinomio que se suma.
· Polinomio &operator - (const Polinomio & p) -> resta al receptor otro polinomio, al polinomio receptor se le resta el polinomio p y el resultado se deja sobre el propio receptor.
POSTCONDICIÓN : el receptor es modificado
PARÁMETROS : p -> polinomio que se resta.
· Polinomio &operator * (const Polinomio & p) -> multiplica el receptor por otro polinomio, al polinomio receptor es multiplicado por p y el resultado se deja sobre el propio receptor.
POSTCONDICIÓN : el receptor es modificado
PARÁMETROS : p -> segundo factor.
· Polinomio &operator * (const float x) -> producto de un polinomio por un escalar, el receptor es multiplicado por el escalar x.
POSTCONDICIÓN : el receptor es modificado
PARÁMETROS : x -> escalar que se multiplica.
· Friend Polinomio &operator * (float x, Polinomio & p) -> producto de un polinomio por un escalar, almacena sobre p el producto x * p.
PARÁMETROS : x -> escalar que se multiplica.
p -> polinomio multiplicado, es modificado.
· Polinomio &operator = (const Polinomio & p) -> operador de asignación para polinomios, el objeto receptor se transforma en una copia de p, su valor anterior se pierde.
POSTCONDICIÓN : el receptor es modificado
PARÁMETROS : p -> polinomio que se copia.
· ~Polinomio () -> destructor, destruye el polinomio receptor, liberando los recursos que usaba
POSTCONDICIÓN : el receptor es modificado
Imprimir un polinomio
Esta función nos va imprimiendo en pantalla cada coeficiente del polinomio.
Polinomio p;
Void Imprimir ()
{
cout << p.Grado ();
for (int i =0; i <=p.Grado(); i++)
if (p.Coef (i) != 0.0)
cout << i << p.Coef (i);
cout << -1;
}
Un polinomio viene definido por un grado y por los coeficientes, el grado es una variables entera que nos dice la potencia más alta de un coeficiente del polinomio, y los coeficientes se almacenan en un vector de float llamado coef.
Vamos a ver la especificación tanto de la función de abstracción como del invariante de la representación del polinomio:
Función de Abstracción
fA : rep ------> p (x)
(coef, grado) ------> coef[0] + coef[1]*x + coef[2] *x2 + ... + coef[grado] * xgrado.
Invariante de Representación
Cualquier objeto del tipo rep: {coef, grado} debe verificar:
- grado >= 0.
- coef apunta a un vector con grado+1 componentes.
- coef[grado] != 0 ó grado == 0.
De manera que la clase Polinomio en C++ tendría el siguiente aspecto:
Class Polinomio
{
Public:
Polinomio ();
Polinomio (float * c, int g);
Polinomio(const Polinomio & p);
float Coef (int i) const;
int Grado () const;
float operator () (float x) const;
bool operator == (const Polinomio & p) const;
bool operator != (const Polinomio & p) const;
friend Polinomio &operator - (Polinomio & p);
Polinomio &operator + (const Polinomio & p);
Polinomio &operator - (const Polinomio & p);
Polinomio &operator * (const Polinomio & p);
Polinomio &operator * (const float x);
friend Polinomio &operator * (float x, Polinomio & p);
Polinomio &operator = (const Polinomio & p);
~Polinomio();
Private:
int grado;
float *coef;
bool Nulo () const;
Ostream & operator << (ostream & s, const Polinomio & p) ;
}
Pasemos ahora a ver la implementación de cada una de las primitivas enunciadas con anterioridad en C++:
static bool Cero (float x)
{
const float cero = 1e-20;
return (x <= cero);
}
inline bool Polinomio::Nulo() const
{
return ((grado == 0) && Cero(coef[0]));
}
Polinomio::Polinomio()
{
coef = new float[1];
assert(coef != 0);
coef[0] = 0;
grado = 0;
}
Polinomio::Polinomio(float * Coef, int Grado)
{
grado = Grado;
coef = new float[grado + 1];
assert(coef != 0);
for (int i = 0; i <= grado; i++)
coef[i] = Coef[i];
}
Polinomio::Polinomio(const Polinomio & p)
{
grado = p.grado;
coef = new float[grado];
assert(coef != 0);
for (int i = 0; i <= grado; i++)
coef[i] = p.coef[i];
}
float Polinomio::Coef(int i) const
{
assert (0 <= i);
if (i > grado)
return 0;
return coef[i];
}
inline int Polinomio::Grado() const
{
return grado;
}
float Polinomio::operator()(float x) const
{
float suma = 0;
for (int i = grado; i > 0; i--)
suma = x * (coef[i] + suma);
suma += coef[0];
return suma;
}
Polinomio & Polinomio::operator=(const Polinomio & p)
{
if (&p == this)
return *this;
if (grado == p.grado)
{
for (int i = 0; i <= grado; i++)
coef[i] = p.coef[i];
return *this;
}
grado = p.grado;
delete [] coef;
coef = new float[p.grado + 1];
for (int i = 0; i <= grado; i++)
coef[i] = p.coef[i];
return *this;
}
bool Polinomio::operator==(const Polinomio & p) const
{
if (grado != p. grado)
return false;
int i = grado;
while ((coef[i] == p.coef[i]) && i >= 0)
i--;
return (i < 0);
}
inline bool Polinomio::operator!=(const Polinomio & p) const
{
return !(*this == p);
}
Polinomio & operator-(Polinomio & p)
{
for (int i = 0; i <= p.grado; i++)
p.coef[i] = -p.coef[i];
return p;
}
Polinomio & Polinomio::operator+(const Polinomio & p)
{
if (p.grado < grado)
{
for (int i = 0; i <= p.grado; i++)
coef[i] += p.coef[i];
}
else
if (p.grado > grado)
{
float * c = new float[p.grado + 1];
assert (c != 0);
int i = 0;
for (; i <= grado; i++)
c[i] = coef[i] + p.coef[i];
for (; i <= p.grado; i++)
c[i] = p.coef[i];
delete [] coef;
coef = c;
grado = p.grado;
}
else
{
int i = grado;
while (Cero(coef[i] + p.coef[i]) && (i >= 0))
--i;
if (i < 0) {
delete [] coef;
grado = 0;
coef = new float[1];
coef[0] = 0.0;
}
else
if (i == grado) {
for (int i = 0; i <= grado; i++)
coef[i] += p.coef[i];
}
else
{
grado = i;
float * c = new float[i + 1];
assert (c != 0);
for (; i >= 0; i--)
c[i] = coef[i] + p.coef[i];
delete [] coef;
coef = c;
}
}
return *this;
}
Polinomio & Polinomio::operator-(const Polinomio & p)
{
if (p.grado < grado)
{
for (int i = 0; i <= grado; i++)
coef[i] -= p.coef[i];
}
else
if (p.grado > grado)
{
float * c = new float[p.grado + 1];
assert (c != 0);
int i = 0;
for (; i <= grado; i++)
c[i] = coef[i] - p.coef[i];
for (; i <= p.grado; i++)
c[i] = -p.coef[i];
delete [] coef;
coef = c;
grado = p.grado;
}
else
{
int i = grado;
while (Cero(coef[i] - p.coef[i]) && (i >= 0))
--i;
if (i < 0)
{
delete [] coef;
grado = 0;
coef = new float[1];
coef[0] = 0.0;
}
else
if (i == grado)
for (int i = 0; i <= grado; i++)
coef[i] -= p.coef[i];
else
{
grado = i;
float * c = new float[i + 1];
assert (c != 0);
for (; i >= 0; i--)
c[i] = coef[i] - p.coef[i];
delete [] coef;
coef = c;
}
}
return *this;
}
Polinomio & Polinomio::operator*(const Polinomio & p)
{
if (p.Nulo() || Nulo())
{
delete [] coef;
coef = new float[1];
assert(coef != 0);
coef[0] = 0;
grado = 0;
}
else
{
int nuevo_grado = grado + p.grado;
float * c = new float[nuevo_grado + 1];
assert(c != 0);
for (int k = 0; k <= nuevo_grado; k++)
c[k] = 0.0;
for (int j = p.grado; j >= 0; j--)
for (int i = 0; i >= grado; i--)
c[i+j] += p.coef[j] * coef[i];
grado = p.grado;
delete [] coef;
coef = c;
}
return *this;
}
Polinomio & Polinomio::operator*(const float x)
{
if (Cero(x))
{
delete [] coef;
coef = new float[1];
coef[0] = 0;
grado = 0;
}
else
{
for (int i = 0; i <= grado; i++)
coef[i] *= x;
}
return *this;
}
Polinomio & operator*(float x, Polinomio & p)
{
if (Cero(x))
{
delete [] p.coef;
p.coef = new float[1];
p.coef[0] = 0;
p.grado = 0;
}
else
{
for (int i = 0; i <= p.grado; i++)
p.coef[i] *= x;
}
return p;
}
ostream & operator<<(ostream & s, const Polinomio & p)
{
if (p.Grado() > 1)
{
int i = p.Grado();
s << p.Coef(i) << " x^" << i;
for (i--; i > 1; i--)
if (!Cero(p.Coef(i)))
s << " + " << p.Coef(i) << "x^" << i;
if (!Cero(p.Coef(1)))
s << " + " << p.Coef(1)<< "x";
if (!Cero(p.Coef(0)))
s << " + " << p.Coef(0);
}
else if (p.Grado() == 1)
{
s << p.Coef(1) << "x";
if (!Cero(p.Coef(0)))
s << " + " << p.Coef(0);
}
else
s << p.Coef(0);
return s;
}
inline Polinomio::~Polinomio()
{
delete [] coef;
}