Está en la página 1de 7

UNIVERSIDAD NACIONAL DE COLOMBIA

Herramientas Computacionales
Profesor: Diego Milanes
Alumno :Juan Pablo Vargas Acosta
1
Tarea Utilizando AClass
10 de septiembre de 2014
Analisis del codigo
Una vez descomprimido el archivo encontramos, 5 carpetas y un archivo make, las carpetas
bin, obj, out se encuentran vacias, en las otras dos carpetas inc y src tienen partes crusiales del
codigo las cuales vamos a empezar a analizar.
Empezamos en la carpeta inc (posible diminutivo para include) en esta carpeta vamos a en-
contrar 2 archivos, func y tools ambos con extensiones .hh, en estos archivos se van a denir los
prototipos de las funciones que vamos a usar luego.
archivos .hh son usados en la programacion orientada a objetos para la decion de las clases
y de las funciones para despues ser llamadas reduciendo el tamao del programa principal. Otra
venteja de usar la extencion .hh es que podemos usar las deniciones hechas hay en muchos otros
codigos y si necesitamos modicar las funciones lo hacemos directamente desde este archivo.
En nuestro caso se van a denir las funciones de la siguiente manera :
inline double RangeLenght() const { return _max - _min; };
inline double StepSize() const { return _h; };
inline double Eval( double x ){ return _formula.Eval( x ); };
std::vector<double> FindRoots();
TGraph
*
FunctionGraph();
TGraph
*
DerivativeGraph( std::string method );
TGraph
*
CumulativeGraph( std::string method );
observamos el uso de la funcion inline que es beneciosa para la denicion de algoritmos cortos,
evita problemas de denicion multiple de una funcion y perimite que el compilador ejecute mas
rapido el programa.
En en Func.hh tambien tenemos la denicion de el vector FindRoots utilizando la biblioteca
vector este vector sera utilizado para encontrar los ceros de la funcion que introduzca el usuario,
el uso de esta biblioteca es muy importante pues nos permite variar la cantidad de memoria des-
tinada para ese vector de forma dinamica.
Para terminar con esta parte del codigo tenemos la creacion de metodos TGraph que van incluidas
en este header lo cual simplicara el codigo a futuro.
2
En el archivo tools.hh encontramos la denicion de una serie de prototipos void que se en-
cargan de entregar los resultados gracos del programa, algo bastante signicativo es el uso de
namespace:
namespace Tools
{
void SetCanvas( TCanvas& c);
void SetGraph( TGraph& g );
void Print( TGraph& g,
std::string title, std::string xtitle, std::string out,
int color = 0, int style = 0, int width = 0 );
}
Esto lo usamos cuando puede existir algun tipo de ambiguedad respecto a los nombres de va-
riables,clases, funciones.. etc. Veremos luego el uso de esto al abordar el archivo main.cc.
Pasamos ahora a los archivos de asociados a los headers anteriormente mencionados , em-
pezamos por el archivo func.cc, lo primero que notamos es la inclucion del header homonimo
func.hh el cual se incluye especicando su hubicacion relativa como sigue:
#include "../inc/func.hh"
Adentrandonos en el codigo vemos la denicion de los prototipos mencionados anteriormen-
te, vemos el uso de punteros this que permite identicar de manera directa y evitando cualquier
ambiguedad para el compilador una variable en particular.
Algo interezante tambien es la eciencia a la hora de implementar loops en el codigo velando
que sean los menores posibles, ejemplo de esto es la denicion de los metodos para hacer las de-
rivadas y sus gracas en el mismo loop,en cuanto a los metodos numericos utilizados, se hallaron
las derivadas de 2 maneras, la primera conocida como forward differentiation que hace parte de
la familia de las nite differentiation
1
la cual tiene en el programa una forma similar a la siguiente
:
f (x
1
h) f (x
0
h)
h
(1)
Donde h es la longitud de los intervalos y los x =x
1
x
0
se toman muy pequeos. La otra forma
es la denominada central differentation tambien perteneciente a la mencionada familia, la cual
toma la forma de :
f (x +
1
2
h) f (x
1
2
h) (2)
Para el calculo de la segunda derivada se uso el metodo mencionado en clase, caso analogo
con el calculo de las integrales.
Prestando atencion al archivo tools.cc encontramos una sintaxis similar al encabezado del an-
terior archivo:
#include "../inc/tools.hh"
Donde especicamos la ubicacion relativa del header, ahora notamos la importancia de hacer
denido el namespace tools pues por medio de este hacemos que nuestras funciones prototipo
realicen mas procesos que los que hacen tradicionalmente las bibliotecas de root como se ilustra
enseguida:
1
estas son expreciones de la forma f (x +b) f (x +a) que permiten el calculo aproximado de derivadas
3
void Tools::SetGraph( TGraph& g ){
g. GetXaxis( ) -> SetNdivisions( 605 );
g. GetXaxis( ) -> SetLabelSize( 0.06 );
g. GetXaxis( ) -> SetTitleSize( 0.07 );
g. GetXaxis( ) -> SetLabelOffset( 0.02 );
g. GetXaxis( ) -> SetTitleOffset( 1.1 );
g. GetYaxis( ) -> SetNdivisions( 605 );
g. GetYaxis( ) -> SetLabelSize( 0.06 );
g. GetYaxis( ) -> SetTitleSize( 0.07 );
g. GetYaxis( ) -> SetLabelOffset( 0.01 );
g. GetYaxis( ) -> SetTitleOffset( 1.25 );
g. SetMarkerSize( 1 );
g. SetMarkerStyle( 9 );
g. SetTitle( " " );
Aqui vemos como se aprovecho SetGraph para ejecutar varios procesos de una sola vez, aho-
rrando espacio.
En este archivo sera el que se encarge de presentar los gracos obtenidos por los procesos
numericos anterior mente mencionados.
Para culminar conel cuerpo del programa tenemos el archivo main.cc enel cual se va a integrar
todos los anteriores esfuerzos, en el se va a presentar la sintaxis con la cual el usuario podra correr
el programa, para tal proposito se usara una cadena de caracteres, como los archivos anteriores
importaremos los header con la sintaxis usual, aqui tambien se hace necesaria la presencia del
namaspace tools:
#include "../inc/func.hh"
#include "../inc/tools.hh"
algo importante al respecto es el uso del operador delete el cual se encarga de limpiar la cade-
na de caracteres que almacena la formula introducida por el usuario.
Una parte muy importante del programa es el archivo make, pues el nos permite ejecutar el
programa haciendo uso de las librerias de root, esenciales para introducir la funcion de manera
simbolica
2
y gracar, este nos arroja como resultado nal el ejecutable program almacenado en
la carpeta bin, este se genera a partir de los archivos compilados que tienen extencion .o
3
y de
main.cc, los archivos .o son obtenidos de compilar func.cc y su header al igual que tools.cc y su res-
pectiva header, en el makele tambien se hace necesario decirle al compilador donde queremos
que nos deje los resultados, asi es como denimos variables asociadas a la ubicacion al principio
de este, al nal de este se incluye el target clean que permite borrar los resultados de la compila-
cion de una forma facil y rapida.
Correcion e implementacion de nuevos algoritmos
Una vez entendemos el codigo estamos en capacidad de mejorar ciertas cosas y agregar otras,
una de las primeras cosas que uno podria hacer es por ejemplo desacerce de la funcion itostr, la
cual es un algoritmo que transforma numeros enteros en cadenas de caracteres, sin embargo en
este programa no estamos requiriendo de sus servicios, funcion itostr en tools.cc
2
pues se usa el metodo TFormula para crear un espacio en la memoria con esta
3
la extencion o hace alusion a que estos archivos ya fueron traducidos al lenguage de la maquina son denominados
objects
4
std::string Tools::itostr( int ival )
{
char buffer[20];
sprintf( buffer, "%i" , ival );
return std::string( buffer );
}
otro pequeo detalle era un warning que mostraba el compilador asociado al archivo tools.cc
el cual advertia de una supuesta presencia no deseada en el metodo SetTitle pues para g++ el ar-
gumento FALSE no era valido, nos desaciamos de este problemilla remplasando :
g. SetTitle(FALSE);
Por:
g. SetTitle( " " );
Otra pequea cosa que yo encontre es en el archivo func.cc en la funcion que asignamos para
imprimir las raices usamos el operador signed :
for( int i = 0; i<(signed)roots.size(); ++i )
std::cout << " root " << i << " = " << roots.at( i ) << std::endl;
return roots;
}
El uso de este me parecio inecesario pues estamos recorriendo las entradas del vector roots y pues
el numero asociado a las entradas siempre es mayor a cero, este operador permite diferenciar un
binario positivo de uno negativo i.e. 110unsi gnes =7 y 110si gned =1. Probe el codigo sin este
operador y funciona bien.
Otra cosa de la cual uno de puede deshacer es de las funciones RangeLengthy StepSize dinidas
como inlines en el header func:
inline double RangeLenght() const { return _max - _min; };
inline double StepSize() const { return _h; };
Pues estas funciones no son llamadas despues y por lo tanto el programa cumple su objetivo
sin tener que incluirlas, ademas las tareas que estas funciones podrian realizar, son hechas de
manera directa en el archivo func.cc.
Respecto a los cambios al programa se le agrego la posibilidad de que el usuario introduzca la
derivada de manera simbolica, y el programa retorna como resultado los ceros de la funcion, asi
consecuentemente hallando los maximos y minimos de la funcion. Para esto se va a modicar un
poco la clase FUNC, empezamos por el header en el cual agregaremos en el constructor de la clase
lo siguiente:
-objeto nuevo en el encapsulamiento de la clase:
TFormula _derivada;
-redefinicion de la funcion Func:
Func( TFormula f,TFormula d, int steps, double min, double max );
-definicion de una nueva funcion inline:
inline double Evald( double x ){return
_derivada.Eval( x ); };
5
Con eso termina la modicacion del archivo func.hh, ahora en el archivo func.cc se anexara lo
siguiente :
--en la inicializacion de los objetos de la
funcion prototipo se agragara el objeto
_derivada( d )
--en la impresion en donde se le informa al
usuario los parametros que el programa va a tener
en cuenta se pondra :
std::cout << " Derivada : " <<
_derivada.GetExpFormula() << std::endl;
--con esto mostraremos en pantalla la
ecuacion
Dentro de la funcion FindRoots haremos lo siguiente:
definimos dos nuevos vectores:
std::vector<double> cerosm;
std::vector<double> cerosmi;
--hay se almacenaran los ceros, en cerosm se
almacenaran los maximos y en cerosmi los minimos
if (this->Evald( xi )
*
this->Evald( xip1 )
<=0. && this->Evald( xi )< this->Evald( xip1
) ) cerosm.push_back( 0.5
*
(xi+xip1) );
--entontramos los maximos por criterio de la
primera derivada
if (this->Evald( xi )
*
this->Evald( xip1 ) <=0.
&& this->Evald( xi )> this->Evald( xip1 ) )
cerosmi.push_back( 0.5
*
(xi+xip1) );
--encontramos los minimos usando el mismo
criterio
--aca se usa la funcion nueva inline que
permitira encontrar las raices de la derivada
std::cout << "\nFunc::FindRoots() --> The max
of the function are (+-" << 0.5
*
_h << "):" <<
std::endl;
for( int i = 0; i<(double)cerosm.size(); ++i
) std::cout << " max " << i << " = " <<
cerosm.at( i ) << std::endl;
std::cout << "\nFunc::FindRoots() --> The max
of the function are (+-" << 0.5
*
_h << "):" <<
std::endl;
for( int i = 0; i<(double)cerosmi.size(); ++i
6
) std::cout << " min " << i << " = " <<
cerosmi.at( i ) << std::endl;
--aca se imprimen los resultados obtenidos en el
anterior algoritmo
return cerosm;
return cerosmi;
--retornamos el resultado
Eso fue todo en el archivo func.cc, ahora debemos modicar el archivo main.cc en el se va a
poner lo siguiente:
--se define la siguiente cadena de caracteres
std::string derivada = "";
--se asigna memoria a la derivada por medio de la
condicion:
if ( std::string( argv[ i ] ) == "-d" )
derivada = std::string( argv[ i+1 ] );
--se agrega descripcion de uso para el usuario:
std::cout << "-d : Derivate formula.
If formula includes (,) or / use \\ before
the
symbol (i.e sin(x) -> sin\\(x\\) )"
<<std::endl;
--se modifica la creacion del objetos
*
f asociado
a la clase Func de la siguiente manera :
Func
*
f = new Func( TFormula( "",
formula.c_str()),TFormula( "",
derivada.c_str()), nsteps, min, max);
Otras modicaciones como las de cambiar el nombre de las gracas que van a residir en la
carpeta out fueron descartadas pues esto ocasiona una acumulacion de archivos inecesarios.
7

También podría gustarte