Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Equipo V_05
- Santiago Puyol
- Nicolás Ubieto
- Borja Zapata
- */
- #include <iostream>
- #include <cstdio>
- #include <cmath>
- #include <string.h>
- #define MAXFONDOS 20
- #define MAXOPERACIONES 100
- #define MAX_CHAR 100
- using namespace std;
- /** Representa una fecha */
- struct fecha
- {
- int dia, mes, agno;
- };
- typedef struct fecha Fecha;
- /** Representa una operación de compra o venta
- de un cierto número de participaciones del fondo
- cuyo identificador se almacena en el campo 'idFondo'. El número
- de unidades (participaciones) es positivo si la operación
- es una compra; es negativo si se trata de un venta.
- El campo 'precioUnidad' es el precio de compra/venta
- de cada participación en esta operación.
- El valor de la operación es el resultado, positivo
- o negativo, de multiplicar el número de participaciones
- por su precio.
- */
- struct operacion
- {
- int idFondo;
- Fecha fechaOperacion;
- double unidades, precioUnidad;
- };
- typedef struct operacion Operacion;
- /** Representa un fondo de inversión
- cuyo identificador se almacena en el campo 'idFondo'.
- El nombre del fondo está en el campo 'nombreFondo'.
- El campo 'precio' es el precio de cada participación del fondo
- en la fecha 'fechaReferencia'
- */
- struct fondo
- {
- int idFondo;
- double precio;
- Fecha fechaReferencia;
- char nombreFondo[MAX_CHAR];
- };
- typedef struct fondo Fondo;
- /** Representa una función cuya expresión analítica
- es la suma de una colección de términos de la forma
- C·z^t. El coeficiente C y el exponente t del término
- i-ésimo se almacenan en las correspondientes
- componentes de los arrays 'coeficiente' y 'exponente'.
- */
- struct funcion
- {
- int nTerminos;
- double coeficiente[MAXOPERACIONES+1];
- double exponente[MAXOPERACIONES+1];
- };
- typedef struct funcion Funcion;
- /** Representa el nombre de un fondo junto
- con su TIR en una determinada fecha.
- */
- struct tirFondo
- {
- Fecha fecha;
- char fondo[MAX_CHAR];
- double tir;
- };
- typedef struct tirFondo TirFondo;
- /** Determina si un año es o no bisiesto.
- Entradas: un entero (a>1700), el año (parámetro dato)
- Salidas: true si y sólo si a representa un
- año bisiesto en el calendario gregoriano
- (resultado de la función).
- */
- bool esBisiesto(int a);
- /** Calcula el número de días de un año. Esto es,
- devuelve 366 si el año es bisiesto y 365 en otro caso.
- Entradas: un entero (a>1700), el año (parámetro dato)
- Salidas: un entero, el número de días del año a
- según el calendario gregoriano (resultado de función).
- */
- int diasAgno(int a);
- /** Calcula el número de días de un mes en un año dado.
- Entradas: dos enteros, 1<=m<=12 (el mes) y a>1700 el año.
- (parámetros dato)
- Salidas: un entero, el número de días del mes m en el
- año a según el calendario gregoriano (res. de función).
- */
- int diasMes(int m, int a);
- /** Dada una fecha, calcula la fracción de año que ha transcurrido
- desde el comienzo del año hasta las 00:00:00 horas del día
- que representa la fecha. Esto es, el número real (entre 0 y 1)
- que resulta al dividir el número de días desde el principio de
- año hasta el día de la fecha dividido por el número total de días
- del año.
- Entradas: una fecha válida (parámetro dato).
- Salidas: un real, la fracción de año transcurrida hasta la fecha
- (resultado de función).
- */
- double fraccionAgno(Fecha f);
- /** Calcula el número de años transcurridos entre dos fechas.
- Entradas: dos fechas, f1 y f2, tales que f1 es anterior a f2
- (parámetros dato).
- Salidas: un real, el número de años transcurridos entre las
- dos fechas (resultado de función).
- */
- double agnosEntreDosFechas(Fecha f1, Fecha f2);
- /** Dadas dos fechas, este subalgoritmo devuelve
- -1 si la primera es anterior a la segunda
- 0 si las fechas son iguales y
- 1 si la primera es posterior a la segunda.
- Entradas: dos fechas (parámetro dato)
- Salidas: un entero, indicando cual es anterior (res. función).
- */
- int fechaAnterior(Fecha f1, Fecha f2);
- /** Dada una operación de compra/venta de unidades de un fondo,
- calcula el valor de la operación, que será
- positivo si se trata de una compra y negativo si es una venta.
- Entradas: una operación (parámetro dato)
- Salidas: un real, el precio total de la operación (res. función).
- */
- double calculaCapital(Operacion o);
- /** Evalúa una función, representada por un dato de tipo Función,
- en un punto x.
- Entradas: una función, f, y un real x (parámetros dato)
- Salidas: el real f(x) (resultado de función).
- */
- double evaluaFuncion(double x, Funcion f);
- /** Dado un dato de tipo Funcion, calcula una de sus raíces en el
- intervalo [0,3].
- Entradas: un dato, f, de tipo Funcion (parámetro dato)
- Salidas: un real en el intervalo [0,3] que es raíz de f
- (resultado de función).
- */
- double calculaTIR(Funcion f);
- /** Dado un puntero f a una estructura de tipo FILE que apunta a un fichero
- de texto tipo fFondo abierto para lectura, lee la información necesaria
- para construir un dato de tipo Fondo.
- Entradas: un dato, f, de tipo puntero a FILE
- Salidas: un dato de tipo Fondo construido a partir de la información
- del fichero (resultado de función)
- */
- Fondo leeFondo(FILE* f);
- /** Dado un array de registros de tipo TirFondo así
- como su número de componentes, devuelve ese mismo
- array ordenado en orden creciente de fecha
- Entradas: un array de datos de tipo TirFondo y un entero que representa
- el número de datos almacenados en el array.
- Salidas: el mismo array de tipo TirFondo, ordenado en orden creciente de
- fecha.
- */
- void ordenaCrecientePorFecha(TirFondo arrTIR[], int nComponentes);
- int main()
- {
- //Variables relacionadas con los ficheros
- FILE* fich1;
- FILE* fich2;
- FILE* fichsalida;
- char nfs[MAX_CHAR], nf1[MAX_CHAR], nf2[MAX_CHAR];
- //Variables auxiliares (para comparar datos)
- Fondo auxFond;
- double auxTIR = 0;
- Operacion auxOper = {0};
- Funcion auxFun = {0};
- //Contadores o índices
- double totalParts = 0;
- int fondoIndex = 0;
- //El array de salida, es lo que devolveremos con los tirs ordenados
- TirFondo tirs[MAXFONDOS];
- printf("Introduce a continuacion el nombre del fichero de fondos: ");
- scanf("%s", nf1);
- printf("\nAhora introduce el nombre del fichero de operaciones: ");
- scanf("%s", nf2);
- fich1 = fopen(nf1,"r");
- if(fich1 == NULL){
- printf("Ha habido un problema con la apertura del fichero de fondos.");
- }
- else{
- fich2 = fopen(nf2,"rb");
- if(fich2 == NULL){
- printf("Ha habido un problema con la apertura del fichero de operaciones.");
- }
- else{
- auxFond = leeFondo(fich1);
- fread(&auxOper,sizeof(Operacion),1,fich2);
- do{
- //Ponemos las variables auxiliares a 0 (cada iteración del bucle
- //mayor es un fondo distinto)
- totalParts = 0;
- auxTIR = 0;
- auxFun.nTerminos = 0;
- for(int i = 0; i < MAXOPERACIONES + 1; i++){
- auxFun.exponente[i] = 0;
- auxFun.coeficiente[i] = 0;
- }
- //Leemos los datos de la operación a procesar
- do{
- //Nota: podemos usar un do-while porque hemos asumido que hay al menos 1 operación de cada fondo, si no
- //no podríamos saber si la 1º corresponde al primer fondo
- auxFun.coeficiente[auxFun.nTerminos] = calculaCapital(auxOper);
- auxFun.exponente[auxFun.nTerminos] = agnosEntreDosFechas(auxOper.fechaOperacion,auxFond.fechaReferencia);
- //Necesitamos un contador de las unidades totales para sacar el valor final
- totalParts += auxOper.unidades;
- auxFun.nTerminos++;
- fread(&auxOper,sizeof(Operacion),1,fich2);
- }while(auxOper.idFondo == auxFond.idFondo && !feof(fich2));
- auxFun.coeficiente[auxFun.nTerminos] = -1 * totalParts * auxFond.precio;
- auxFun.nTerminos++;
- auxTIR = calculaTIR(auxFun);
- tirs[fondoIndex].fecha = auxFond.fechaReferencia;
- strcpy(tirs[fondoIndex].fondo,auxFond.nombreFondo);
- tirs[fondoIndex].tir = auxTIR;
- fondoIndex++;
- auxFond = leeFondo(fich1);
- }while(!feof(fich1));
- ordenaCrecientePorFecha(tirs,fondoIndex);
- printf("Introduce ahora el nombre del fichero de salida (es un fichero de texto): ");
- scanf("%s",nfs);
- //Este pequeño bloque hace que la extensión del archivo de salida
- //siempre sea txt. Si los ultimos 4 caracteres de la cadena no son
- //".txt" concatena el ".txt"
- char auxSub[5];
- if(strcmp(strcpy(auxSub, nfs + strlen(nfs) - 4), ".txt") != 0) strcat(nfs,".txt");
- fichsalida = fopen(nfs,"w");
- if(fichsalida == NULL){
- printf("No se ha podido abrir el fichero de salida.");
- }
- else{
- for(int i = 0; i < fondoIndex; i++){
- fprintf(fichsalida,"%02i/%02i/%04i %+.4lf %s",tirs[i].fecha.dia,tirs[i].fecha.mes,tirs[i].fecha.agno,tirs[i].tir,tirs[i].fondo);
- }
- fclose(fichsalida);
- }
- fclose(fich2);
- }
- }
- fclose(fich1);
- }
- /** Determina si un año es o no bisiesto.
- */
- bool esBisiesto(int a)
- {
- return (a%400==0) || (a%4==0 && a%100!=0);
- }
- /** Calcula el número de días de un año. Esto es,
- devuelve 366 si el año es bisiesto y 365 en otro caso.
- */
- int diasAgno(int a)
- {
- if(esBisiesto(a)) return 366;
- else return 365;
- }
- /** Calcula el número de días de un mes en un año dado.
- */
- int diasMes(int m, int a)
- {
- switch(m)
- {
- case 2:
- if (esBisiesto(a)) return 29;
- else return 28;
- case 4:
- case 6:
- case 9:
- case 11:
- return 30;
- default:
- return 31;
- }
- }
- /** Dada una fecha, calcula la fracción de año que ha transcurrido
- desde el comienzo del año hasta el día que representa la fecha.
- Esto es, el número real (entre 0 y 1) que resulta al dividir
- el número de días desde el principio de año hasta el día de la
- fecha dividido por el número total de días del año.
- */
- double fraccionAgno(Fecha f)
- {
- double dias=f.dia-1;
- for(int i=1; i<f.mes; i++)
- {
- dias=dias+diasMes(i,f.agno);
- }
- return dias/diasAgno(f.agno);
- }
- /** Calcula el número de años transcurridos entre dos fechas.
- */
- double agnosEntreDosFechas(Fecha f1, Fecha f2)
- {
- return f2.agno-f1.agno+fraccionAgno(f2)-fraccionAgno(f1);
- }
- /** Determina si una fecha es anterior a otra
- */
- int fechaAnterior(Fecha f1, Fecha f2)
- {
- double diferencia=agnosEntreDosFechas(f1,f2);
- if (diferencia>0) return -1;
- else if(diferencia==0) return 0;
- else return 1;
- }
- /** Dada una operación de compra/venta de unidades de un producto
- financiero, calcula el valor de la operación, que será
- positivo si se trata de una compra y negativo si es una venta.
- */
- double calculaCapital(Operacion o)
- {
- return o.precioUnidad*o.unidades;
- }
- /** Evalúa una función, representada por un dato de tipo Función,
- en un punto x.
- */
- double evaluaFuncion(double x, Funcion f)
- {
- double b=0;
- for(int j=0; j<f.nTerminos; j++)
- b=b+f.coeficiente[j]*pow(x,f.exponente[j]);
- return b;
- }
- /** Dado un dato de tipo Funcion, calcula una de sus raíces en el
- intervalo [0,3].
- */
- double calculaTIR(Funcion f)
- {
- double inf = 0, fin = 3;
- const double eps = 1.0e-12;
- while (fin-inf>eps)
- {
- double med = (inf+fin)/2;
- double valor = evaluaFuncion(med, f);
- if (valor<0) inf = med;
- else if (valor>0) fin = med;
- else inf = fin = med;
- }
- return ((inf+fin)/2-1)*100;
- }
- Fondo leeFondo(FILE* f){
- Fondo fnd = {0};
- fscanf(f,"%i %i %i %i %lf \\n",&fnd.idFondo, &fnd.fechaReferencia.dia,
- &fnd.fechaReferencia.mes, &fnd.fechaReferencia.agno, &fnd.precio);
- fgets(fnd.nombreFondo,MAX_CHAR,f);
- return fnd;
- }
- void ordenaCrecientePorFecha(TirFondo arrTIR[], int nComponentes){
- //Se ordenan por el ordenamiento de burbuja, aunque no es el más
- //eficiente la diferencia de eficiencia resulta despreciable dado un MAXFONDOS de 20
- TirFondo auxTIR;
- for(int i = 0 ; i <= nComponentes - 1; i++){
- for(int j = 0; j < nComponentes - 1 - i; j++){
- if(fechaAnterior(arrTIR[j].fecha,arrTIR[j+1].fecha) == 1){
- auxTIR = arrTIR[j];
- arrTIR[j] = arrTIR[j+1];
- arrTIR[j+1] = auxTIR;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement