Site hosted by Angelfire.com: Build your free website today!
 Search: Lycos Angelfire     Dating Search
share this page Share This Page  report abuse Report Abuse  build a page Edit your Site  show site directory Browse Sites  hosted by angelfire
    « Previous | Top 100 | Next » hosted by angelfire

Universidad de Costa Rica

 

Escuela de Ciencias de la
Computación e Informática

 

Segunda Tarea Programada:
Calculadora de Polinomios

 

CI-1201 Programación II

 

 

 

Profesor
Adolfo Di Mare

 

 

Estudiantes:
Eileen Rodríguez D. A34418
Katia Montoya M.    A43493

 

Grupo 002
II Ciclo 2005

 

 

 

 

 


Tabla de Contenidos

 

Tabla de Contenidos....................................................................................................... . 4

Introducción.........................................................................................................................3

Descripción Problema a Resolver..................................................................................3

    Planteo............................................................................................................................3

Objetivos.......................................................................................................................3

Requerimientos...................................................................................................... ...4

Abstracción...........................................................................................................................5

Especificación de la clase.............................................................................5

Operaciones y métodos.........................................................................................5

Eficiencia.....................................................................................................................7

Especificación del programa....................................................................... ..7

Arquitectura del Programa............................................................................ ..8

Implementación................................................................................................................. .9

Modelo de la Clase............................................................................................. ..9

    Invariante de la Clase……………………………………………………………………………………………9

Arquitectura Interna del Programa....................................................... .12

Compilador Usado.................................................................................................. 13

¿Cómo compilar el programa?....................................................................... 13

Guía del uso del programa............................................................................................ 14

Datos de prueba del programa.................................................................................... 14

Formato de los Datos de Prueba...................................................................14

Entradas Vs Salidas Esperadas del Programa................................. 14

Código Fuente............................................................................................................15

Bibliografía........................................................................................................................ 57

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Introducción

 

            Uno de los principales objetivos dentro de la temática del curso y de la programación en sí, consiste enormemente en la comprensión de lo que significa la reutilización de código o software, es decir, utilizar funciones de software ya existentes como bloques de construcción para crear programas. De tal forma que la reutilización se convierta en un factor importante dentro de la programación orientada a objetos.

            De manera, que una de las fuentes para la realización del programa, consistió en tomar otro programa, parte de éste para crear el programa actual, además de que el objetivo de ambos es similar, la ejecución de un programa que tome operaciones aritméticas sencillas y las ejecute.

            Es posible acceder al programa en sí, desde las direcciones de Internet:

_     http://www.angelfire.com/freak3/a34418

_     http://www.angelfire.com/moon2/a43493

 

 

Descripción Problema a Resolver

Ø      Planteo:

La implementación de un programa ejecutable capaz de llevar a cabo operaciones aritméticas básicas  como la suma, resta multiplicación y división(no está implementada en esta tarea) ya sea mediante la utilización de números enteros, racionales (primera tarea, para verla, vaya a http://www.angelfire.com/freak3/a34418 ó http://www.angelfire.com/moon2/a43493) y polinomios. Estableciendo como resultado y solución una calculadora polimórfica creada para funciones sencillas pero importantes, en el empleo de alguna operación sin complejidad.

 

Ø      Objetivos:

-          Entender el proceso de reutilización de código

-          Comprender la elaboración del programa, mediante la vista del código

-          Desarrollar habilidad y facilidad a la hora de la compilación

-          Manejo más rápido mediante un editor de texto de C++, como por ejemplo el Visual Studio 6.0

-          Obtener la solución al problema, la ejecución de la calculadora polimórfica

 

Ø      Requerimientos:

-          Compilador C++, ya sea el de Visual Studio 6.0, el Visual Studio.Net  o el Borland C++.

-          Para la ejecución, obviamente se necesita el código fuente (más adelante se presentará).

-          Para mayor entendimiento o claridad, el archivo doxigen, en el cual se muestra más detalladamente la implementación del programa.

-          Alguno guía de compilación y ejecución del programa (más adelante se presentará).

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Abstracción

            Especificación de las Clases

 

Clase Pol-calc.cpp:

            En esta clase se sitúa la función principal para la ejecución del programa, es decir, la función main, la cual tiene como fin llamar a funciones de la biblioteca estándar  para llevar a cabo sus tareas. Dentro de la declaración de la clase, se establece, básicamente, las estructuras sobre las cuales se lleva a cabo el tipo de operación a realizar, de tal manera, que se permite escoger, que función aritmética ha seleccionado para llevarla a cabo.

 

Operaciones / Métodos

 

*  int main() : función principal en la que empieza la ejecución del programa

*  Se declaran dos variables r (para el último valor ingresado) y acum (acumulador de la calculadora) de tipo Poly, que hacen referencia a la clase poly.cpp además de una variable char llamada op que hace referencia a la operación a efectuar.

*  Se inicializa la variable acum. en cero  y se despliega el valor de inicio del acumulador mediante el operador de inserción de flujo, así obtenido el valor se introduce con el operador >>.

*  while: se introduce la estructura de control, para poder leer las operaciones que están siendo solicitadas, es decir, si lo introducido por el usuario equivale a un punto, finaliza el programa, pero si no, comienza el switch y dar paso a la selección de la operación a realizar.

*  int test_main()

*  inline void DO_Poly_Poly( const char * STR)

*  void Poly_Poly()

 

Clase Poly.cpp:

             Se establecen las implementaciones para la clase “Poly”.

 

 

 

Funciones / Métodos

 

*  bool check_ok( const Poly& P )

*  void Poly::SetTerm (float c, unsigned d)

*  void Poly::Adjust_Degree()

*  Poly& Poly::operator = (const Poly& o)

*  Poly Poly::operator - () const

*  Poly& Poly::operator += (const Poly& o) : Método de Suma

*  Poly& Poly::operator -= (const Poly& o) : método que resta

*  Poly& Poly::operator *= (const Poly& P)

*  Poly operator + (const Poly &x, const Poly &y)

*  Poly operator - (const Poly &x, const Poly &y)

*  Poly operator * (const Poly &x, const Poly &y)

*  void Coef_String( double r, char * res )

*  void Poly::From_String(const char* STR)

 

Clase Poly.h:

            Define el tipo “Poly”, así como implementa las principales operaciones aritméticas para los polinomios

 
Funciones /Métodos

 

*  inline bool operator != (const Poly& x, const Poly& y)

*  private:

    enum { Max_Degree = 6  :Grado Máximo de cualquier polinomio

*  Poly(const Poly& o) { (*this) = o; } : Constructor de copia

*  Poly(float c) { (*this) = c; } : Constructor desde un escalar

*  ~Poly() { }     : Destructor

*  private:

    unsigned m_degree;          :Grado del polinomio

    float    m_coef[Max_Degree];  :Coeficientes del polinomio

 

 

 

 

Eficiencia:

      El programa no es muy eficiente, puesto que no cualquier usuario puede llevar cabo la ejecución, ya que contiene ciertas pautas que a la hora de ejecutar el programa no llegue a suceder nada, a razón de la poca complejidad con la que cuenta el programa y la poca estructuración que se emplea para su realización. No funciona tan libremente como cualquier calculadora.

 

Especificación del Programa

            Este programa es una calculadora polimórfica muy simple que funciona con los siguientes objetos:

 

    -  long, int: números enteros

    - rational:  números racionales (primera tarea)

    - Poly:      polinomios

 

    La calculadora funciona de la siguiente manera:

    - Al principio el valor acumulado es  [ 0 ]

    - Se puede usar cualquier de los 4 operadores aritméticos, excepto la división la cual no está implementada

    - Para terminar se usa el operador de salida punto "."

 

    Traza de ejecución:

   

    [0] > + [ 2 / 3 ]

    [2/3] > / [ 6 / 2 ]

    [2/9] > * [ 18 ]

    [4] > - [ 45 / 9 ]

    [-1] > / [ 13 / 8 ]

    [-8/13] > * [ 2 ]

    [-16/13] > + [ 7 ]

    [75/13] > .

    [75/13] >

   

 

Arquitectura del Programa



Cuadro de texto: bool.h

 


Cuadro de texto: Poly.obj Cuadro de texto: <cstdlib>
<cctype>
<iostream.h>
Cuadro de texto: Poly.h Cuadro de texto: <iostream.h>
<iomanip>
<climits>
Cuadro de texto: Pol-calc.obj

 

Cuadro de texto: Poly.cpp Cuadro de texto: Pol-calc.cpp

 

 

 

 

 

Cuadro de texto: Pol-calc.exe

 

 


Implementación

               El modelo, mediante el cual esta organizado el programa, es obviamente el de los polinomios definido como:

                                               P(x) = a0 xn + a1 xn – 1 + ... + a n

            Donde n Î N (número natural) ; a0, a1, a2, ... , an son coeficientes reales (pertenecientes al conjunto de los números reales) y "x" se denomina coeficiente indeterminado. Para la implementación del programa se siguió  claramente la especificación de acuerdo con los grados del polinomio, su funcionalidad, es decir, por ejemplo, que el  grado de un polinomio: está determinado por el término que posee el valor de potencia más alto.

Ejemplo:

P(x) = x2 + 3x – 4 Polinomio de grado 2

R(x) = 3 Polinomio de grado 0

Q(x) = x5 + 7 x3 – 2  Polinomio de grado 5

M(x) = 0 Polinomio nulo.

           

 

            Modelo de la Clase

Clase Poly.h

·          Private

           Enum { Max_Degree = 6}

·          Private

      unsigned m_degree;          

        float    m_coef[Max_Degree];

    void Adjust_Degree();

 

·          Public:

    Poly() : m_degree(0) { m_coef[0] = 0.0;

                           memset( (void*)this, 0, sizeof(Poly) );  } 

    Poly(const Poly& o) { (*this) = o; }

    Poly(float c) { (*this) = c; }

    ~Poly() { }     

 

Clase Poly.cpp

·          void Poly::SetTerm (float c, unsigned d) {

    m_coef[d] = c;

    unsigned i ;

    if ( d > m_degree ) {

                for (i=d-1; i>= m_degree+1; i--) {

            m_coef[i] = 0.0;

        }

                m_degree = d;

    }

·          void Poly::Adjust_Degree() {

    while ( (m_degree>0) && (m_coef[m_degree] == 0.0) ) {

        --m_degree;

    }

·          Poly& Poly::operator = (const Poly& o) {

    m_degree = o.m_degree;

    for (unsigned i= 0; i <= m_degree; ++i) {

        m_coef[i] = o.m_coef[i];

    }

    return *this;

}

·          Poly Poly::operator - () const {

    Poly tmp;

 

    tmp.m_degree = m_degree;

    for (unsigned i= 0; i <= m_degree; ++i) { 

        tmp.m_coef[i] = - m_coef[i];

    }

 

    return tmp;

}

 

·          Poly& Poly::operator += (const Poly& o) {

                if (m_degree < o.m_degree){         

                               unsigned min = m_degree;

                               m_degree = o.m_degree

                               unsigned i = 0;

                              for (i; i<= m_degree; ++i){

                                               m_coef[i] += o.m_coef[i];}

                                               for (i; i <= o.m_degree; ++i){

                                               m_coef[i] = o.m_coef[i]}

                } else

                               unsigned min = o.m_degree;

                for (unsigned i = 0; i <= o.m_degree; ++i){

                               m_coef[i] += o.m_coef[i];

                }

                Adjust_Degree ();

                               return *this;} 

·          Poly& Poly::operator -= (const Poly& o) {

                         if (m_degree < o.m_degree){

                               unsigned min = m_degree;

                               m_degree = o.m_degree;

                               unsigned i = 0;

                               for (i; i<= o.m_degree; ++i){

                                               m_coef[i] -= o.m_coef[i];}

                               for (i; i <= o.m_degree; ++i){

                                               m_coef[i] = o.m_coef[i];}

                } else

                               unsigned min = o.m_degree;

               

                for (unsigned i = 0; i <= o.m_degree; ++i){

                               m_coef[i] -= o.m_coef[i];}

                Adjust_Degree ();

                               return *this;}

·          Poly& Poly::operator *= (const Poly& P) {

     Poly tmp;

    unsigned i, j;

    tmp.m_degree = m_degree + P.m_degree ;

    for (i=1; i<=tmp.m_degree; ++i) { // rellena con ceros

        tmp.m_coef[i]= 0;

    }

    for (i=0; i<=m_degree; ++i) {

        for (j=0; j<=P.m_degree; ++j) { // multiplica

            tmp.m_coef[i+j] += m_coef[i] * P.m_coef[j];

        }

    }

    Adjust_Degree();

    return (*this = tmp);

}

 

 

Clase Pol-calc.cpp

·          int main() {

                    void Poly_Poly(); Poly_Poly();

·          int test_main() {

    void Poly_Poly(); Poly_Poly();

   return 0;}

·          void Poly_Poly()

 

 

Invariante de la Clase

            La invariante se presenta si el grado del polinomio se excede, de tal maneta que  se caracteriza que

- Un polinomio está almacenado en su vector "this->m_coef[]" que contiene  1 +       Poly::Max_Degree  números de punto flotante ("float)".

            - En "m_coef[i]" está almacenado el coeficiente del término "x^i".

             - En "m_degree" está almacenado el grado del polinomio.

            - El polinomio cero se representa con m_degree == 0 && m_coef[0] == 0.0

 

 

 

 

 

 

 

    Por ejemplo, el polinomio x^3 + 2x^2 se representa así:

 

    polinomio                grado

    x^3 + 2x^2                 3

 

                      0     1     2     3     4     5                Max_Degree

                 +-----+-----+-----+-----+-----+-----+ ... +-----+-----+-----+

                  | 0.0 | 0.0 | 2.0 | 1.0 | @$? | !+" | ... | @*? | ^\* | ??? |

                 +-----+-----+-----+-----+-----+-----+ ... +-----+-----+-----+

                                              ^

    m_coef[]                             |

    m_degree == 3 --------------+

 

bool check_ok( const Poly& P ) {

    assert( false && "NO IMPLEMENTADO ==> check_ok( const Poly& )" );

    if ( P.m_degree > Poly::Max_Degree ) {

        /// Invariante: El grado del polinomio no puede exceder "Poly::Max_Degree".

        return false;

    }

    else if ( (P.m_degree > 0) && (P.m_coef[P.m_degree] == 0.0) ) {

        /// Invariante: El coeficiente del término de mayor grado de un polinomio no constantes deber ser diferente de "0.0".

        return false;

    }

    return true;

} // check_ok()

   

Arquitectura Interna

 

            Este programa está diseñado para la implementación de una calculadora polimórfica. El usuario introduce los datos, estos son internados en el programa, se verifica si la información introducida es compatible con las especificaciones del programa, se recurre hacia cual operación ha sido seleccionada, (ya sea suma, resta, multiplicación), el programa realiza la operación y se vincula un espacio en memoria para la información introducida, la operación antes, y la operación después, es decir, el resultado es almacenado, de tal manera, que es devuelto, es decir, es desplegado, con la finalidad de demostrar el resultado de la operación seleccionada y efectuada.

 

 

 

Compilador Usado

·         Para la ejecución del programa fue utilizado el compilador del Visual Studio 6.0 C++.

 

 

 

Cómo Compilar el Programa?

 

            Primero que todo, se debe buscar si en su computador está instalado un compilador de C++, compatible, en nuestro caso, utilizamos el visual Studio 6.0, para verificar, haga clic en el botón inicio, váyase a archivos de programas, y búsquelo si no, es así puede estar alojado en el archivo, desarrollo, una vez encontrado, haga clic en el icono perteneciente al Visual en este caso, ya abierto el programa, y sin la necesidad de haber creado primeramente un proyecto váyase a files, dele clic en el botón open, y seleccione los archivos conjunto para poder compilarlos, claro, está es necesario tener los archivos guardados ya sea en su computador, o bien en un disquete o CD, una vez ubicados los archivos haga clic en abrir, e inmediatamente le aparecerán los archivos dentro del visual, ya sea que los vaya abriendo uno por uno, o todos a la vez. Ya hecho esto, digite control + f7 o bien al lado izquierdo dentro de la barra superior hay un icono con una flechita para abajo, esto le permitirá compilar el programa, seguidamente, digite f7, para darle build y tener listo el programa, seguidamente seleccione control + f5 y su programa se ejecutará, si no se ejecuta inmediatamente podrá ser porque necesita el proyecto, sin embargo el computador se lo hará saber, mediante una ventanita de advertencia, haga clic en sí, y eso permitirá que se cree, permitiendo la ejecución del programa.

 

 

Guía de Uso del Programa

 

            En el caso de que quiera bajar el programa de internet, que lo puede encontrar en www.angelfire.com/freak3/a34418 o www.angelfire.com/moon2/a43493 , en el link de tareas, haga clic si desea guardarlo o si desea abrirlo, seguidamente guárdelo en un dispositivo, abra el visual Studio, compílelo, y seguidamente ejecútelo.

 

 

Datos de Prueba del Programa

            Formato de los Datos de Prueba        

           

Los datos de prueba consisten en la información que es introducida, la cual es evaluada por medio del programa, por ejemplo asignada a  la variable m_degree, mediante la entrada puesta por el usuario que se transforma en o.m_degree, así mismo y si la entrada es compatible se procederá a la selección de la operación si esta es válida o inválida, si es inválida se desplegará el warning advirtiendo al usuario, y  si es válida, se desplegará, el resultado, de la operación que se haya realizado.

 

Entradas vs Salidas Esperadas

[  ] == [0]

[ -2 ] == [-2.]

[ - 2 ] == [-2.]

[ - 2.0 ] == [-2.]

[ - 2.3 ] == [-2.3]

[ + x ] == [2.x]

[ x ] == [2.x]

[ 0 x ] == [0]

[ 0 ] == [0]

[ 2 ] == [2.]

[ -2 ] == [-2.]

[ - 2 ] == [-2.]

[0 ] == [0]

[2 ] == [2.]

[-2 ] == [-2.]

[- 2 ] == [-2.]

[ 0] == [0]

[ 2] == [2.]

[ -2] == [-2.]

[ - 2] == [-2.]

[0] == [0]

[2] == [2.]

[-2] == [-2.]

[ 2x ] == [4.x]

[-2x ] == [-4.x]

[- 2x ] == [-4.x]

[ 2x] == [4.x]

[ -2x] == [-4.x]

[ - 2x] == [-4.x]

[2x] == [4.x]

[-2x] == [-4.x]

 

 

P1 == [2.1x^2 + x - 0.3]

P2 == [x^2 + 1.]

P3 == [-x^3 - 2.x - 3.7]

P4 == [-x^4 - 1.]

 

 

P1 == [4.2x^2 + x - 0.3]

P2 == [2.x^2]

P3 == [-2.x^3 - 2.x - 3.7]

P4 == [-2.x^4 - 1.]

 

 

P2 == [x^2 + 1]

 

        Código Fuente

// Poly.cpp        (c) 2005 adolfo@di-mare.com

 

/** \file Poly.cpp

    \brief Implementaciones para la clase \c "Poly"

 

    \author Adolfo Di Mare <adolfo@di-mare.com>

    \date   2005

 

    - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04

*/

 

#include "Poly.h"

#include "StringCH.h"

 

#include  <cstdlib>

#include  <cctype>     // isdigit()

 

OPEN_namespace(ADH)

 

#include  <assert.h>   // assert()

 

/** Verifica la invariante de la clase \c Poly

 

    - Un polinomio está almacenado en su vector \c "this->m_coef[]"

      que contiene <code> 1 + Poly::Max_Degree </code> números de

      punto flotante \c ("float)".

    - En \c "m_coef[i]" está está almacenado el coeficiente del

      término \c "x^i".

    - En \c "m_degree" está almacenado el grado del polinomio.

    - El polinomio cero se representa con

      <code> m_degree == 0 && m_coef[0] == 0.0 </code>.

 

    Por ejemplo, el polinomio x^3 + 2x^2 se representa así:

    \code

    polinomio                grado

    x^3 + 2x^2                 3

 

       0     1     2     3     4     5                Max_Degree

    +-----+-----+-----+-----+-----+-----+ ... +-----+-----+-----+

    | 0.0 | 0.0 | 2.0 | 1.0 | @$? | !+" | ... | @*? | ^\* | ??? |

    +-----+-----+-----+-----+-----+-----+ ... +-----+-----+-----+

                         ^

    m_coef[]             |

    m_degree == 3 -------+

    \endcode

 

    \remark

    Debido a que cualquier valor binario que esté almacenado en un

    número de punto flotante \c ("float)" siempre es un valor válido,

    en la implementación se asume que los número almacenados en casillas

    superiores a <code> this->m_degree </code> tienen un valor cualquiera

    (basura), y por eso eso valores no están inicializados en cero \c "0.0".

 

    \remark

    Libera al programador de implementar el método \c Ok()

    - http://www.di-mare.com/adolfo/binder/c04.htm#sc11

*/

bool check_ok( const Poly& P ) {

    assert( false && "NO IMPLEMENTADO ==> check_ok( const Poly& )" );

    if ( P.m_degree > Poly::Max_Degree ) {

        /// Invariante: El grado del polinomio no puede exceder \c "Poly::Max_Degree".

        return false;

    }

    else if ( (P.m_degree > 0) && (P.m_coef[P.m_degree] == 0.0) ) {

        /// Invariante: El coeficiente del término de mayor grado de un polinomio no constantes deber ser diferente de \c "0.0".

        return false;

    }

    return true;

} // check_ok()

 

/** Fuerza a que el término \c "d" de \c "*this" tenga coeficiente \c "coef".

 

     - Si <code>( coef == 0.0 && Degree() = d )</code>,

       el grado del \c "*this" queda reducido, y puede

       eventualmente hacerse cero.

*/

void Poly::SetTerm (float c, unsigned d) {

    m_coef[d] = c;

    unsigned i ;

    if ( d > m_degree ) {

                  for (i=d-1; i>= m_degree+1; i--) {

            m_coef[i] = 0.0;

        }

      m_degree = d;

    }

}; // TPoly::SetTerm

 

/** Modifica \c "*this" para que <code>( m_coef[m_degree] != 0.0 )</code> siempre que <code>( m_degree > 0 )</code>

 

    - Restaura la invariante de la clase

*/

void Poly::Adjust_Degree() {

    while ( (m_degree>0) && (m_coef[m_degree] == 0.0) ) {

        --m_degree;

    }

}  // Poly::Adjust_Degree()

 

 

/** Copia desde \c "o"

 

    - El valor anterior de \c "*this" se pierde

 

    \par Complejidad:

         O( \c o.Degree() )

 

    \returns *this

 

    \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05

*/

Poly& Poly::operator = (const Poly& o) {

    m_degree = o.m_degree;

    for (unsigned i= 0; i <= m_degree; ++i) {

        m_coef[i] = o.m_coef[i];

    }

 

    return *this;

}  // operator =

 

/** Intercambia los valores de \c "*this" y \c "o"

 

      \par Complejidad:

         O( \c o.Degree() )

 

    \returns *this

 

    \see http://www.di-mare.com/adolfo/binder/c04.htm#sc08

*/

Poly& Poly::Swap ( Poly& o ) {

    #ifdef INEFICIENTE

        Poly tmp = o;  // Reqiere O(n) espacio adicional

        o = *this;     // Reqiere O(n) tiempo adicional

        *this = tmp;

    #else

        if (m_degree < o.m_degree) {

            for (unsigned i = 0; i <= m_degree; ++i) { // copia el principio

                float tmp = o.m_coef[i];

                o.m_coef[i] = (*this).m_coef[i];

                this->m_coef[i] = tmp;

            }

            for (; i <= o.m_degree; ++i) {  // copia la cola

                m_coef[i] = o.m_coef[i];

            }

        }

        else {

            for (unsigned i = 0; i <= o.m_degree; ++i) { // copia el principio

                float tmp = o.m_coef[i];

                o.m_coef[i] = (*this).m_coef[i];

                this->m_coef[i] = tmp;

            }

            for (; i <= m_degree; ++i) {  // copia la cola

                m_coef[i] = o.m_coef[i];

            }

        }// INEFICIENTE

    #endif

 

    return *this;

}

 

/// ¿ x == y ?

bool operator == (const Poly &x, const Poly &y) {

    if (x.m_degree != y.m_degree ) { // mismo grado

        return false;

    }

    for (unsigned i= 0; i <= x.m_degree; ++i) {

        if (x.m_coef[i] != y.m_coef[i]) {      // mismos coeficientes

            return false;

        }

    }

    return true;

}  // operator ==

 

/// \c "-x"

///

/// - Menos unario

/// - Calcula y retorna el valor \c "-x"

Poly Poly::operator - () const {

    Poly tmp;

 

    tmp.m_degree = m_degree;

    for (unsigned i= 0; i <= m_degree; ++i) {  // copia la cola

        tmp.m_coef[i] = - m_coef[i];

    }

 

    return tmp;

}  // operator -

 

#include <assert.h> // assert()

 

/// Le suma a \c "*this" el valor de \c "o"

Poly& Poly::operator += (const Poly& o) {

      if (m_degree < o.m_degree){

                 

                  unsigned min = m_degree;

                  m_degree = o.m_degree;

 

                  unsigned i = 0;

 

                  for (i; i<= m_degree; ++i){

                             m_coef[i] += o.m_coef[i];

                  }

 

                             for (i; i <= o.m_degree; ++i){

                             m_coef[i] = o.m_coef[i];

                            

                  }

      } else

 

                  unsigned min = o.m_degree;

     

      for (unsigned i = 0; i <= o.m_degree; ++i){

                  m_coef[i] += o.m_coef[i];

      }

      Adjust_Degree ();

                  return *this;

}  // operator +=

 

/// Le resta a \c "*this" el valor de \c "o"

Poly& Poly::operator -= (const Poly& o) {

  

      if (m_degree < o.m_degree){

                 

                  unsigned min = m_degree;

                  m_degree = o.m_degree;

 

                  unsigned i = 0;

 

                  for (i; i<= o.m_degree; ++i){

                             m_coef[i] -= o.m_coef[i];

                  }

 

                  for (i; i <= o.m_degree; ++i){

                             m_coef[i] = o.m_coef[i];

                  }

      } else

 

                  unsigned min = o.m_degree;

     

      for (unsigned i = 0; i <= o.m_degree; ++i){

                  m_coef[i] -= o.m_coef[i];

      }

      Adjust_Degree ();

                  return *this;

 

}  // operator -=

 

/// Multiplica \c "*this" por \c "P"

Poly& Poly::operator *= (const Poly& P) {

    Poly tmp;

    unsigned i, j;

    tmp.m_degree = m_degree + P.m_degree ;

    for (i=1; i<=tmp.m_degree; ++i) { // rellena con ceros

        tmp.m_coef[i]= 0;

    }

    for (i=0; i<=m_degree; ++i) {

        for (j=0; j<=P.m_degree; ++j) { // multiplica

            tmp.m_coef[i+j] += m_coef[i] * P.m_coef[j];

        }

    }

    Adjust_Degree();

    return (*this = tmp);

}  // operator *=

 

/// \c "x+y"

///

/// - Calcula y retorna la suma \c "x+y"

Poly operator + (const Poly &x, const Poly &y) {

    Poly res = x;

    res += y;

    return res;

}  // operator + ()

 

/// \c "x-y"

///

/// - Calcula y retorna la resta \c "x-y"

Poly operator - (const Poly &x, const Poly &y) {

    Poly res = x;

    res -= y;

    return res;

}  // operator - ()

 

/// \c "x*y"

///

/// - Calcula y retorna la multiplicaci¢n \c "x*y"

Poly operator * (const Poly &x, const Poly &y) {

    Poly res = x;

    res *= y;

    return res;

}  // operator * ()

 

/// \c "x/y"

///

/// - Calcula y retorna la divisi¢n \c "x/y"

///

/// \pre <code> y != 0 </code>

Poly operator / (const Poly &x, const Poly &y) {

    assert( !true && "Poly::operator / (x,y) ==> NO IMPLEMENTADO" );

    x.IsZero();

    y.IsZero();

    return Poly();

}  // operator / ()

 

/// Eval£a el polinomio en el valor \c "x"

///  - Para calcular p(x) usa la Regla de Horner.

float Poly::Eval (float x ) const {

    float sum =0.0;

    for (unsigned i = m_degree; i>0; i--) {

        sum= x * sum + m_coef[i];

    }

    return sum;

}

 

#include <string.h>

#include <stdlib.h>

#include <math.h>

#include <assert.h>

 

/// Cantida de d¡gitos usado en \c Coef_String() para invocar \c gcvt()

const unsigned Coef_String_Digits = 7;

 

/** Convierte el núumero "r" a su representaci¢n de hilera

    - Hace un buen intento por eliminar la parte decimal si es cero.

    - La transformación a hilera se hace invocando la función \c gcvt()

       -  char *gcvt(double value, int ndec, char *buf);

       - \c gcvt() NO es una funci¢n de la biblioteca estándar

    - Se guardan \c "Coef_String_Digits" dígitos significativos nada más

 

    \pre

    - <code> sizeof(res) &gt;= 7 + Coef_String_Digits</code>

*/

void Coef_String( double r, char * res ) {

    const char Blank = ' ';

    const char Cero  = '0';

    const char Dot   = '.';

 

    // gcvt() es la rutina que hace todo el trabajo

    gcvt( r, Coef_String_Digits,  res ); // gcvt() NO es estándar...

 

    char* first = res;

    while ( *first == Blank ) {

        first++; // se brinca los blancos del principio

    }

    while ( *first == Cero ) {

        first++; // se brinca los ceros del principio

    }

    if ( ( *first == Dot ) || ( *first == 0 ) ) {

        first--;

        assert( *first == Cero ); // recupera el £ltimo '0'

    }

    unsigned len_first = strlen(first);

    if ( first != res ) { // aqu¡ elimina los ceros del principio

        memmove( res, first, 1+len_first );

    }

 

    first = res;

    while ( (*first != Dot) && (*first != 0) ) {

        first++; // busca '.' o EOS

    }

 

    if ( *first == Dot ) {

        char* decimals = first;

        while ( *decimals == Cero ) {

            decimals++; // se brinca los ceros de los decimales

        }

        if ( *decimals == 0 ) { // se acabo "res"

            *first = 0; // elimina todos los decimales que son '0'

        }

    }

} // Coef_String()

 

/** Construye y retorna una hilera que contiene el valor de \c "*this"

    - Es responsabilidad del programador destruir la hilera retornada

      para recuperar la memoria dinámica en uso.

    - Los coeficientes del polinomio se graban con una precisión

      de \c "Coef_String_Digit" dígitos significativos.

 

    \code

    "[x^2 + x]"

    "[11x^3 - 2]"

    "[-x^3 - 2x^2 + 1.4]"

    \endcode

 

    \remarks

    El programador debe liberar la memoria dinámica asociada

    a la hilera retornada.

*/

const char* Poly::To_String() const {

    StringCH coef; // Cada uno de los términos del polinomio

    StringCH STR;  // Hilera resultado

    const unsigned MX = (

        ( Coef_String_Digits + 7 > 40 )

        ? Coef_String_Digits + 7

        : 40

    );

    char STR_num[ MX ];

 

    unsigned g = m_degree; // iterador sobre m_coef[]

    STR += '[';

 

    g = m_degree+1;

    do { // for [g == m_degree] ==> [g == 0]

        --g;

        coef.MakeEmpty();

        if (m_coef[g] > 0.0) { // +3 x^ 2

            if (g != m_degree) {

                STR += " + ";   // separa el término del anterior

            }

 

            if ((m_coef[g] != 1.0) || (g==0)) {

                Coef_String( m_coef[g], STR_num );

                STR += STR_num;

            }

 

            if (g>1) {

                itoa( g, STR_num, 10 );

                STR += "x^";

                STR += STR_num;

            }

            else if (g == 1) {

                STR += 'x';

            }

        }

        else if (m_coef[g] < 0.0) {  // -3 x^ 2

            if (g == m_degree) {

                STR += '-';     // este es el primero término

            }

            else {

                STR += " - ";   // separa el término del anterior

            }

 

            if ( (m_coef[g] != -1.0) || (g==0) ) {

                Coef_String( m_coef[g], STR_num );

                STR += STR_num+1; // se brinca el signo

            }

 

            if (g>1) {

                itoa( g, STR_num, 10 );

                STR += "x^";

                STR += STR_num;

            }

            else if (g == 1) {

                STR += 'x';

            }

        }

    } while ( g != 0 );

 

    if ( 1 == strlen( STR ) ) {

        STR.Append('0');

    }

    STR += ']';

 

    char * ret = new char[ 1+strlen(STR) ];

    memcpy( ret, STR, 1+strlen(STR) );

    return ret;

} // Poly::To_String()

 

/** Usa la hilera \c "STR" para almacenar ese valor en \c "*this"

 

    - El formato de lectura es similar al que produce \c "Poly::To_String()".

 

    \code

    "[x^2 + x]"

    "[11x^3 - 2]"

    "[-x^3 - 2x^2 + 1.4]"

    \endcode

*/

void Poly::From_String(const char* STR) {

    Zero(); // anula P

 

    // GRAN ciclo para procesar cada uno de los términos

    Poly Term; // término obtenido en este ciclo

 

    const char* pBegin = STR+1; // se salta el '['

    while ( *pBegin != ']' ) {

        const char * pEnd = pBegin;

 

        // coeficiente ==> "coef"

        bool has_digit = false;

        bool is_positive = true;

        while ( (*pEnd != ']') && (*pEnd != 'x') && (*pEnd != 'X') ) {

            if ( isdigit(*pEnd) ) {

               has_digit = true;

            }

            else if ( *pEnd == '+') {

                pBegin = pEnd;

            }

            else if ( *pEnd == '-') {

                is_positive = !is_positive;

                pBegin = pEnd+1;

            }

            ++pEnd;

        }

 

        float coef;

        if ( has_digit ) {

           coef = atof( pBegin ); // 3.2 x^ 22 + x + 2 x + 1

        }

        else {

            if ( (*pEnd == 'x') || (*pEnd == 'X') ) {

                coef = 1.0;

            }

            else if ( (*pEnd == ']') || (*pEnd == '+') || (*pEnd != '-') ) {

                coef = 0.0;

            }

            else {

                coef = 1.0;

            }

        }

        if (!is_positive) {

            coef = -coef;

        }

        unsigned exp;

 

        // exponente ==> "exp"

        pBegin = pEnd;

        bool has_exponent = false;

        bool has_big_exponent = false;

 

        // camina sobre la hilera para determinar si hay o no exponente

        // - Término de grado 0     ==> " -2.3 "

        // - Término de grado 1     ==> " -2.3 x "

        // - Término de mayor grado ==> " -2.3 x^ +24 "

        bool done = false;

        for (;;) {

            if (*pEnd == ' ') {

                // done = false;

            }

            else if (*pEnd == ']') {

                done = true;

            }

            else if ( (*pEnd == 'X') || (*pEnd == 'x') ) {

                has_exponent = true;

            }

            else if (*pEnd == '^') {

                has_big_exponent = true;

            }

            else {

                done = true;

            }

 

            if (! done) {

                ++pEnd;

            }

            else {

                break;

            }

        }

 

        pBegin = pEnd;

        if ( has_exponent ) {

            if ( has_big_exponent ) { // " -2.3 x^ 24 "

                exp = atol( pBegin );

            }

            else {                    // " -2.3 x "

                exp = 1;

            }

        }

        else {

            exp = 0;                  // " -2.3 "

        }

        Term.Zero();

        Term.SetTerm( coef, exp );

 

        *this += Term; // suma el nuevo término

 

        pBegin = pEnd;

        while ( isdigit(*pBegin) ) {

            ++pBegin;

        }

    }

 

} // Poly::From_String()

 

/** Graba el valor de \c "r" en el flujo \c "COUT"

 

    - Graba el valor en el formato "[-x^3 - 2x^2 + 1.4]".

 

    - Este es el operador que se invoca \c "cout":

     \code

          cout << P << Q;

     \endcode

*/

ostream& operator<< (ostream &COUT, const Poly& P) {

    const char* val = P.To_String();

    COUT << val;

    delete [] (char*)val;

    return COUT;

}  // operator <<

 

 

/** Lee del flujo de texto \c "CIN" el valor de \c "r"

 

    \pre

    El número Poly debe haber sido escrito usando el formato

    "[-x^3 - 2x^2 + 1.4]", aunque es permisible usar algunos blancos.

    - Se termina de leer el valor s¢lo cuando encuentra \c "]".

*/

istream& operator >> (istream &CIN, Poly& P) {

    char ch;  // valor leido, letra por letra, de "CIN"

    StringCH STR;  // Hilera resultado

 

    // lee todo el polinomio como una hilera grandotota

    do {

        CIN >> ch;

        STR += ch;

    } while (ch != ']');

 

    P.From_String( STR );

    return CIN;

/*

    no detecta muuuchos errores...

    ... pero no se supone que el usuario cometa errores...

*/

 

}  // operator >>

 

CLOSE_namespace(ADH)

 

// EOF: Poly.cpp

 

           

 

 

 

// Poly.h   (c) 2005 adolfo@di-mare.com

 

/** \file Poly.h

    \brief Define el tipo \c "Poly"

 

    - La clase \c Poly implementa las operaciones aritméticas

      principales para polinomios

 

    - Permite usar polinomios en cualquier sitio en donde se puedan

      usar valores numéricos, aunque no se pueden usar para comparaciones

      de tamaño.

 

    \author Adolfo Di Mare <adolfo@di-mare.com>

    \date   2005

*/

 

 

#ifndef Poly_h

#define Poly_h ///< Evita la inclusión múltiple

 

#define  INCLUDE_iostream

#include "ADH_port.h"

#include <cstring>

 

OPEN_namespace(ADH)

 

/**  La clase \c Poly implementa las operaciones aritméticas

     principales para números Polyes.

 

     - <code> [x^3 - 2x^2 + 1.4] == [+ 1.4 - 2x^2 + x^3] ...</code>

*/

class Poly {

private:

    enum { Max_Degree = 6 ///< Grado Máximo de cualquier polinomio

    };

//  static const unsigned Max_Degree = 25;

private:

    unsigned m_degree;           ///< Grado del polinomio

    float    m_coef[Max_Degree]; ///< Coeficientes del polinomio

 

    void Adjust_Degree();

 

public:

    // constructores

    Poly() : m_degree(0) { m_coef[0] = 0.0;

                           memset( (void*)this, 0, sizeof(Poly) ); // FEO

                                            }  ///< Constructor de vector

    Poly(const Poly& o) { (*this) = o; } ///< Constructor de copia

    Poly(float c) { (*this) = c; } ///< Constructor desde un escalar

    ~Poly() { }      ///< Destructor

 

    void     SetTerm( float c, unsigned d );

    unsigned Degree() const { return m_degree; }

    float    Coef (unsigned exp) const

        { return (exp > m_degree ? 0.0 : m_coef[exp]); }

 

    /// Retorna \c "true" sólo si <code> *this == 0 </code>

    bool  IsZero() const { return (m_degree == 0) && ( m_coef[0] == 0.0); }

    void  Zero() { m_degree = 0;  m_coef[0] = 0.0;

                           memset( (void*)this, 0, sizeof(Poly) );

                                                   } /// Anula \c "*this"

 

    float Eval (float x ) const;

 

    Poly& operator  = (const Poly&);  // Asignación (copia)

    Poly& operator  = (float c) {  // Asignación desde un escalar

         m_degree = 0;  m_coef[0] = c; return *this; }

    Poly& Swap ( Poly& );

    const char* To_String() const;

    void  From_String(const char*);

 

    Poly& operator += (const Poly&);

    Poly& operator -= (const Poly&);

    Poly& operator *= (const Poly&);

 

    Poly operator - () const;                    // menos unario

 

    friend Poly operator + (const Poly&, const Poly&);

    friend Poly operator - (const Poly&, const Poly&);

    friend Poly operator * (const Poly&, const Poly&);

 

    friend bool operator == (const Poly&, const Poly&);

    friend bool operator != (const Poly&, const Poly&);

 

    friend ostream& operator << (ostream &, const Poly& );

    friend istream& operator >> (istream &,       Poly& );

 

    friend bool check_ok( const Poly& r ); // Ok()

}; // Poly

 

/// ¿ x != y ?

inline bool operator != (const Poly& x, const Poly& y) {

    return !(x == y); // ! ( operator ==(x, y) )

}  // operator !=

 

 

/** \fn unsigned ADH::Poly::Degree() const;

    \brief Retorna el grado del polinomio \c "*this"

     - El gradp de un polinomio es el mayor exponente del polinomio

       que tiene un coeficiente diferente de cero.

     - Si el polinomio es cero, retorna cero.

*/

 

/** \fn float ADH::Poly::Coef (unsigned exp) const;

 

    \brief Devuelve el coeficiente de grado \c "exp" del polinomio \c "*this"

     - Si \c "exp" es más grande que el grado del polinomio entonces

       retorna cero.

*/

 

CLOSE_namespace(ADH)

#endif // Poly_h

 

// EOF: Poly.h

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

// Poly.cpp        (c) 2005 adolfo@di-mare.com

 

/** \file Poly.cpp

    \brief Implementaciones para la clase \c "Poly"

 

    \author Adolfo Di Mare <adolfo@di-mare.com>

    \date   2005

 

    - Why English names??? ==> http://www.di-mare.com/adolfo/binder/c01.htm#sc04

*/

 

#include "Poly.h"

#include "StringCH.h"

 

#include  <cstdlib>

#include  <cctype>     // isdigit()

 

OPEN_namespace(ADH)

 

#include  <assert.h>   // assert()

 

/** Verifica la invariante de la clase \c Poly

 

    - Un polinomio está almacenado en su vector \c "this->m_coef[]"

      que contiene <code> 1 + Poly::Max_Degree </code> números de

      punto flotante \c ("float)".

    - En \c "m_coef[i]" está está almacenado el coeficiente del

      término \c "x^i".

    - En \c "m_degree" está almacenado el grado del polinomio.

    - El polinomio cero se representa con

      <code> m_degree == 0 && m_coef[0] == 0.0 </code>.

 

    Por ejemplo, el polinomio x^3 + 2x^2 se representa así:

    \code

    polinomio                grado

    x^3 + 2x^2                 3

 

       0     1     2     3     4     5                Max_Degree

    +-----+-----+-----+-----+-----+-----+ ... +-----+-----+-----+

    | 0.0 | 0.0 | 2.0 | 1.0 | @$? | !+" | ... | @*? | ^\* | ??? |

    +-----+-----+-----+-----+-----+-----+ ... +-----+-----+-----+

                         ^

    m_coef[]             |

    m_degree == 3 -------+

    \endcode

 

    \remark

    Debido a que cualquier valor binario que esté almacenado en un

    número de punto flotante \c ("float)" siempre es un valor válido,

    en la implementación se asume que los número almacenados en casillas

    superiores a <code> this->m_degree </code> tienen un valor cualquiera

    (basura), y por eso eso valores no están inicializados en cero \c "0.0".

 

    \remark

    Libera al programador de implementar el método \c Ok()

    - http://www.di-mare.com/adolfo/binder/c04.htm#sc11

*/

bool check_ok( const Poly& P ) {

    assert( false && "NO IMPLEMENTADO ==> check_ok( const Poly& )" );

    if ( P.m_degree > Poly::Max_Degree ) {

        /// Invariante: El grado del polinomio no puede exceder \c "Poly::Max_Degree".

        return false;

    }

    else if ( (P.m_degree > 0) && (P.m_coef[P.m_degree] == 0.0) ) {

        /// Invariante: El coeficiente del término de mayor grado de un polinomio no constantes deber ser diferente de \c "0.0".

        return false;

    }

    return true;

} // check_ok()

 

/** Fuerza a que el término \c "d" de \c "*this" tenga coeficiente \c "coef".

 

     - Si <code>( coef == 0.0 && Degree() = d )</code>,

       el grado del \c "*this" queda reducido, y puede

       eventualmente hacerse cero.

*/

void Poly::SetTerm (float c, unsigned d) {

    m_coef[d] = c;

    unsigned i ;

    if ( d > m_degree ) {

            for (i=d-1; i>= m_degree+1; i--) {

            m_coef[i] = 0.0;

        }

            m_degree = d;

    }

}; // TPoly::SetTerm

 

/** Modifica \c "*this" para que <code>( m_coef[m_degree] != 0.0 )</code> siempre que <code>( m_degree > 0 )</code>

 

    - Restaura la invariante de la clase

*/

void Poly::Adjust_Degree() {

    while ( (m_degree>0) && (m_coef[m_degree] == 0.0) ) {

        --m_degree;

    }

}  // Poly::Adjust_Degree()

 

 

/** Copia desde \c "o"

 

    - El valor anterior de \c "*this" se pierde

 

    \par Complejidad:

         O( \c o.Degree() )

 

    \returns *this

 

    \see http://www.di-mare.com/adolfo/binder/c04.htm#sc05

*/

Poly& Poly::operator = (const Poly& o) {

    m_degree = o.m_degree;

    for (unsigned i= 0; i <= m_degree; ++i) {

        m_coef[i] = o.m_coef[i];

    }

 

    return *this;

}  // operator =

 

/** Intercambia los valores de \c "*this" y \c "o"

 

      \par Complejidad:

         O( \c o.Degree() )

 

    \returns *this

 

    \see http://www.di-mare.com/adolfo/binder/c04.htm#sc08

*/

Poly& Poly::Swap ( Poly& o ) {

    #ifdef INEFICIENTE

        Poly tmp = o;  // Reqiere O(n) espacio adicional

        o = *this;     // Reqiere O(n) tiempo adicional

        *this = tmp;

    #else

        if (m_degree < o.m_degree) {

            for (unsigned i = 0; i <= m_degree; ++i) { // copia el principio

                float tmp = o.m_coef[i];

                o.m_coef[i] = (*this).m_coef[i];

                this->m_coef[i] = tmp;

            }

            for (; i <= o.m_degree; ++i) {  // copia la cola

                m_coef[i] = o.m_coef[i];

            }

        }

        else {

            for (unsigned i = 0; i <= o.m_degree; ++i) { // copia el principio

                float tmp = o.m_coef[i];

                o.m_coef[i] = (*this).m_coef[i];

                this->m_coef[i] = tmp;

            }

            for (; i <= m_degree; ++i) {  // copia la cola

                m_coef[i] = o.m_coef[i];

            }

        }

    #endif // INEFICIENTE

 

    return *this;

}

 

/// ¿ x == y ?

bool operator == (const Poly &x, const Poly &y) {

    if (x.m_degree != y.m_degree ) { // mismo grado

        return false;

    }

    for (unsigned i= 0; i <= x.m_degree; ++i) {

        if (x.m_coef[i] != y.m_coef[i]) {      // mismos coeficientes

            return false;

        }

    }

    return true;

}  // operator ==

 

/// \c "-x"

///

/// - Menos unario

/// - Calcula y retorna el valor \c "-x"

Poly Poly::operator - () const {

    Poly tmp;

 

    tmp.m_degree = m_degree;

    for (unsigned i= 0; i <= m_degree; ++i) {  // copia la cola

        tmp.m_coef[i] = - m_coef[i];

    }

 

    return tmp;

}  // operator -

 

#include <assert.h> // assert()

 

/// Le suma a \c "*this" el valor de \c "o"

Poly& Poly::operator += (const Poly& o) {

            if (m_degree < o.m_degree){

                       

                        unsigned min = m_degree;

                        m_degree = o.m_degree;

 

                        unsigned i = 0;

 

                        for (i; i<= m_degree; ++i){

                                   m_coef[i] += o.m_coef[i];

                        }

 

                                   for (i; i <= o.m_degree; ++i){

                                   m_coef[i] = o.m_coef[i];

                                  

                        }

            } else

 

                        unsigned min = o.m_degree;

           

            for (unsigned i = 0; i <= o.m_degree; ++i){

                        m_coef[i] += o.m_coef[i];

            }

            Adjust_Degree ();

                        return *this;

}  // operator +=

 

/// Le resta a \c "*this" el valor de \c "o"

Poly& Poly::operator -= (const Poly& o) {

  

            if (m_degree < o.m_degree){

                       

                        unsigned min = m_degree;

                        m_degree = o.m_degree;

 

                        unsigned i = 0;

 

                        for (i; i<= o.m_degree; ++i){

                                   m_coef[i] -= o.m_coef[i];

                        }

 

                        for (i; i <= o.m_degree; ++i){

                                   m_coef[i] = o.m_coef[i];

                        }

            } else

 

                        unsigned min = o.m_degree;

           

            for (unsigned i = 0; i <= o.m_degree; ++i){

                        m_coef[i] -= o.m_coef[i];

            }

            Adjust_Degree ();

                        return *this;

 

}  // operator -=

 

/// Multiplica \c "*this" por \c "P"

Poly& Poly::operator *= (const Poly& P) {

    Poly tmp;

    unsigned i, j;

    tmp.m_degree = m_degree + P.m_degree ;

    for (i=1; i<=tmp.m_degree; ++i) { // rellena con ceros

        tmp.m_coef[i]= 0;

    }

    for (i=0; i<=m_degree; ++i) {

        for (j=0; j<=P.m_degree; ++j) { // multiplica

            tmp.m_coef[i+j] += m_coef[i] * P.m_coef[j];

        }

    }

    Adjust_Degree();

    return (*this = tmp);

}  // operator *=

 

/// \c "x+y"

///

/// - Calcula y retorna la suma \c "x+y"

Poly operator + (const Poly &x, const Poly &y) {

    Poly res = x;

    res += y;

    return res;

}  // operator + ()

 

/// \c "x-y"

///

/// - Calcula y retorna la resta \c "x-y"

Poly operator - (const Poly &x, const Poly &y) {

    Poly res = x;

    res -= y;

    return res;

}  // operator - ()

 

/// \c "x*y"

///

/// - Calcula y retorna la multiplicaci¢n \c "x*y"

Poly operator * (const Poly &x, const Poly &y) {

    Poly res = x;

    res *= y;

    return res;

}  // operator * ()

 

/// \c "x/y"

///

/// - Calcula y retorna la divisi¢n \c "x/y"

///

/// \pre <code> y != 0 </code>

Poly operator / (const Poly &x, const Poly &y) {

    assert( !true && "Poly::operator / (x,y) ==> NO IMPLEMENTADO" );

    x.IsZero();

    y.IsZero();

    return Poly();

}  // operator / ()

 

/// Eval£a el polinomio en el valor \c "x"

///  - Para calcular p(x) usa la Regla de Horner.

float Poly::Eval (float x ) const {

    float sum =0.0;

    for (unsigned i = m_degree; i>0; i--) {

        sum= x * sum + m_coef[i];

    }

    return sum;

}

 

#include <string.h>

#include <stdlib.h>

#include <math.h>

#include <assert.h>

 

/// Cantida de d¡gitos usado en \c Coef_String() para invocar \c gcvt()

const unsigned Coef_String_Digits = 7;

 

/** Convierte el núumero "r" a su representaci¢n de hilera

    - Hace un buen intento por eliminar la parte decimal si es cero.

    - La transformación a hilera se hace invocando la función \c gcvt()

       -  char *gcvt(double value, int ndec, char *buf);

       - \c gcvt() NO es una funci¢n de la biblioteca estándar

    - Se guardan \c "Coef_String_Digits" dígitos significativos nada más

 

    \pre

    - <code> sizeof(res) &gt;= 7 + Coef_String_Digits</code>

*/

void Coef_String( double r, char * res ) {

    const char Blank = ' ';

    const char Cero  = '0';

    const char Dot   = '.';

 

    // gcvt() es la rutina que hace todo el trabajo

    gcvt( r, Coef_String_Digits,  res ); // gcvt() NO es estándar...

 

    char* first = res;

    while ( *first == Blank ) {

        first++; // se brinca los blancos del principio

    }

    while ( *first == Cero ) {

        first++; // se brinca los ceros del principio

    }

    if ( ( *first == Dot ) || ( *first == 0 ) ) {

        first--;

        assert( *first == Cero ); // recupera el £ltimo '0'

    }

    unsigned len_first = strlen(first);

    if ( first != res ) { // aqu¡ elimina los ceros del principio

        memmove( res, first, 1+len_first );

    }

 

    first = res;

    while ( (*first != Dot) && (*first != 0) ) {

        first++; // busca '.' o EOS

    }

 

    if ( *first == Dot ) {

        char* decimals = first;

        while ( *decimals == Cero ) {

            decimals++; // se brinca los ceros de los decimales

        }

        if ( *decimals == 0 ) { // se acabo "res"

            *first = 0; // elimina todos los decimales que son '0'

        }

    }

} // Coef_String()

 

/** Construye y retorna una hilera que contiene el valor de \c "*this"

    - Es responsabilidad del programador destruir la hilera retornada

      para recuperar la memoria dinámica en uso.

    - Los coeficientes del polinomio se graban con una precisión

      de \c "Coef_String_Digit" dígitos significativos.

 

    \code

    "[x^2 + x]"

    "[11x^3 - 2]"

    "[-x^3 - 2x^2 + 1.4]"

    \endcode

 

    \remarks

    El programador debe liberar la memoria dinámica asociada

    a la hilera retornada.

*/

const char* Poly::To_String() const {

    StringCH coef; // Cada uno de los términos del polinomio

    StringCH STR;  // Hilera resultado

    const unsigned MX = (

        ( Coef_String_Digits + 7 > 40 )

        ? Coef_String_Digits + 7

        : 40

    );

    char STR_num[ MX ];

 

    unsigned g = m_degree; // iterador sobre m_coef[]

    STR += '[';

 

    g = m_degree+1;

    do { // for [g == m_degree] ==> [g == 0]

        --g;

        coef.MakeEmpty();

        if (m_coef[g] > 0.0) { // +3 x^ 2

            if (g != m_degree) {

                STR += " + ";   // separa el término del anterior

            }

 

            if ((m_coef[g] != 1.0) || (g==0)) {

                Coef_String( m_coef[g], STR_num );

                STR += STR_num;

            }

 

            if (g>1) {

                itoa( g, STR_num, 10 );

                STR += "x^";

                STR += STR_num;

            }

            else if (g == 1) {

                STR += 'x';

            }

        }

        else if (m_coef[g] < 0.0) {  // -3 x^ 2

            if (g == m_degree) {

                STR += '-';     // este es el primero término

            }

            else {

                STR += " - ";   // separa el término del anterior

            }

 

            if ( (m_coef[g] != -1.0) || (g==0) ) {

                Coef_String( m_coef[g], STR_num );

                STR += STR_num+1; // se brinca el signo

            }

 

            if (g>1) {

                itoa( g, STR_num, 10 );

                STR += "x^";

                STR += STR_num;

            }

            else if (g == 1) {

                STR += 'x';

            }

        }

    } while ( g != 0 );

 

    if ( 1 == strlen( STR ) ) {

        STR.Append('0');

    }

    STR += ']';

 

    char * ret = new char[ 1+strlen(STR) ];

    memcpy( ret, STR, 1+strlen(STR) );

    return ret;

} // Poly::To_String()

 

/** Usa la hilera \c "STR" para almacenar ese valor en \c "*this"

 

    - El formato de lectura es similar al que produce \c "Poly::To_String()".

 

    \code

    "[x^2 + x]"

    "[11x^3 - 2]"

    "[-x^3 - 2x^2 + 1.4]"

    \endcode

*/

void Poly::From_String(const char* STR) {

    Zero(); // anula P

 

    // GRAN ciclo para procesar cada uno de los términos

    Poly Term; // término obtenido en este ciclo

 

    const char* pBegin = STR+1; // se salta el '['

    while ( *pBegin != ']' ) {

        const char * pEnd = pBegin;

 

        // coeficiente ==> "coef"

        bool has_digit = false;

        bool is_positive = true;

        while ( (*pEnd != ']') && (*pEnd != 'x') && (*pEnd != 'X') ) {

            if ( isdigit(*pEnd) ) {

               has_digit = true;

            }

            else if ( *pEnd == '+') {

                pBegin = pEnd;

            }

            else if ( *pEnd == '-') {

                is_positive = !is_positive;

                pBegin = pEnd+1;

            }

            ++pEnd;

        }

 

        float coef;

        if ( has_digit ) {

           coef = atof( pBegin ); // 3.2 x^ 22 + x + 2 x + 1

        }

        else {

            if ( (*pEnd == 'x') || (*pEnd == 'X') ) {

                coef = 1.0;

            }

            else if ( (*pEnd == ']') || (*pEnd == '+') || (*pEnd != '-') ) {

                coef = 0.0;

            }

            else {

                coef = 1.0;

            }

        }

        if (!is_positive) {

            coef = -coef;

        }

        unsigned exp;

 

        // exponente ==> "exp"

        pBegin = pEnd;

        bool has_exponent = false;

        bool has_big_exponent = false;

 

        // camina sobre la hilera para determinar si hay o no exponente

        // - Término de grado 0     ==> " -2.3 "

        // - Término de grado 1     ==> " -2.3 x "

        // - Término de mayor grado ==> " -2.3 x^ +24 "

        bool done = false;

        for (;;) {

            if (*pEnd == ' ') {

                // done = false;

            }

            else if (*pEnd == ']') {

                done = true;

            }

            else if ( (*pEnd == 'X') || (*pEnd == 'x') ) {

                has_exponent = true;

            }

            else if (*pEnd == '^') {

                has_big_exponent = true;

            }

            else {

                done = true;

            }

 

            if (! done) {

                ++pEnd;

            }

            else {

                break;

            }

        }

 

        pBegin = pEnd;

        if ( has_exponent ) {

            if ( has_big_exponent ) { // " -2.3 x^ 24 "

                exp = atol( pBegin );

            }

            else {                    // " -2.3 x "

                exp = 1;

            }

        }

        else {

            exp = 0;                  // " -2.3 "

        }

        Term.Zero();

        Term.SetTerm( coef, exp );

 

        *this += Term; // suma el nuevo término

 

        pBegin = pEnd;

        while ( isdigit(*pBegin) ) {

            ++pBegin;

        }

    }

 

} // Poly::From_String()

 

/** Graba el valor de \c "r" en el flujo \c "COUT"

 

    - Graba el valor en el formato "[-x^3 - 2x^2 + 1.4]".

 

    - Este es el operador que se invoca \c "cout":

     \code

          cout << P << Q;

     \endcode

*/

ostream& operator<< (ostream &COUT, const Poly& P) {

    const char* val = P.To_String();

    COUT << val;

    delete [] (char*)val;

    return COUT;

}  // operator <<

 

 

/** Lee del flujo de texto \c "CIN" el valor de \c "r"

 

    \pre

    El número Poly debe haber sido escrito usando el formato

    "[-x^3 - 2x^2 + 1.4]", aunque es permisible usar algunos blancos.

    - Se termina de leer el valor s¢lo cuando encuentra \c "]".

*/

istream& operator >> (istream &CIN, Poly& P) {

    char ch;  // valor leido, letra por letra, de "CIN"

    StringCH STR;  // Hilera resultado

 

    // lee todo el polinomio como una hilera grandotota

    do {

        CIN >> ch;

        STR += ch;

    } while (ch != ']');

 

    P.From_String( STR );

    return CIN;

/*

    no detecta muuuchos errores...

    ... pero no se supone que el usuario cometa errores...

*/

 

}  // operator >>

 

CLOSE_namespace(ADH)

 

// EOF: Poly.cpp

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Bibliografía

*  Deitel, Harvey M. y Deitel, Paul J. Cómo programar en C++. Cuarta Edición. Editorial Prentice Hall. México 2003.

*      Escuela de Ciencias de la Computación e Informática, Universidad de Costa Rica, 1994. 
      http://www.di-mare.com/adolfo/p/list.htm
*  Escuela de Ciencias de la Computación e Informática, Universidad de Costa Rica,1994.
                  http://www.di-mare.com/adolfo/p/list.htm
*  Di Mare, Adolfo. La implementación de Rational.pas. Reporte Técnico ECCI-94-03. Proyecto 326-89-019
*  http://platea.pntic.mec.es/~ascatala/polinomios.htm#poli
*  http://soko.com.ar/matem/matematica/polinomio.htm