Skip to content

Commit

Permalink
fixes #2 implementado codigo
Browse files Browse the repository at this point in the history
Correrlo para ver su signatura. El output esta separado en tres partes,
un preambulo indicando que se va a ejecutar, los valores de x para cada
iteracion, y los resultados.

Cada parte esta separada por una linea en blanco. En las iteraciones y
en los resultados solo tomar el primer numero de cada linea, el resto es
texto explicativo. Los resultados siempre se imprimen en el mismo orden.
  • Loading branch information
rasca committed Aug 25, 2013
1 parent 85df50c commit 12122e9
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 55 deletions.
4 changes: 2 additions & 2 deletions codigo/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CC=gcc
CFLAGS=-I.

f_x: f_x.c
$(CC) -o bin/f_x f_x.c $(CFLAGS)
tp1: tp1.c
$(CC) -o bin/tp1 tp1.c $(CFLAGS)
Empty file added codigo/bin/.gitignore
Empty file.
53 changes: 0 additions & 53 deletions codigo/f_x.c

This file was deleted.

290 changes: 290 additions & 0 deletions codigo/tp1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include <float.h>
#include <math.h>
#include <sys/time.h>

#define MAX_ITER 1000

// Funciones para calcular el tiempo
struct timeval start, end;
void init_time()
{
gettimeofday(&start,NULL);
}

double get_time()
{
gettimeofday(&end,NULL);
return (1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec))/1000000.0;
}


/* Funciones a encontrarles la raiz
*
* Se pide tres definiciones, dada g(x) se pide:
* double g(double * x, double * alpha) --> g(x)
* double g1(double * x, double * alpha) --> g'(x) (derivada)
* double g_end(double * x, double * alpha) --> como obtener el resultado desde el x obtenido
*/

/****** f(x) ******/
double f(double * x, double * a) {
// f(x) = x^2 - alpha
return *x * *x - *a;
}

double f1(double * x, double * a) {
// f'(x) = 2 x
return *x * 2;
}
double f_end(double * x, double * a) {
// f_end(x) = 1 / x
// f(x) devuelve beta = sqrt(alpha) por lo que devolvemos la inversa
return 1.0 / *x;
}

/****** e(x) ******/
double e(double * x, double * a) {
// e(x) = 1 / x^2 - alpha
return 1 / (*x * *x) - *a;
}

double e1(double * x, double * a) {
// e'(x) = -2 / (x^3)
return -2 / (*x * *x * *x);
}
double e_end(double * x, double * a) {
// e_end(x) = 1 / x
// e(x) devuelve 1 / sqrt(alpha) por lo que no hacemos nada
return *x;
}

/* Metodos a utilizar para encontrar la raices
*
* Se piden dos definiciones para cada metodo:
* metodo_start(x_prev, x_next, alpha) --> elije los valores x0 y x1
* metodo_iter(x_prev, x_next, alpha, g, g1) --> realiza una iteracion
*/

/****** newton ******/
void newton_start(double * x_prev, double * x_next, double * alpha) {
// No modifico los valores de entrada de x0 y x1
return;
}

void newton_iter(double * x_prev, double * x_next, double * alpha, double (*g)(double *, double *), double (*g1)(double *, double *)) {
// x_n+1 = x_n - g(x) / g'(x)
*x_next = *x_prev - (*g)(x_prev, alpha) / (*g1)(x_prev, alpha);
*x_prev = *x_next;
}

/****** secante ******/
void secante_start(double * x_prev, double * x_next, double * alpha) {
// No modifico los valores de entrada de x0 y x1
return;
}

void secante_iter(double * x_prev, double * x_next, double * alpha, double (*g)(double *, double *), double (*g1)(double *, double *)) {
// x_n+1 = x_n - ( x_n - x_n-1 ) / ( g(x_n) - g(x_n-1) ) * g(x_n)
double aux = *x_next;
if (fabs(*x_next - *x_prev) < DBL_MIN) { // or DBL_EPSILON?
// ya terminamos, sino dividimos por 0
return;
}
*x_next = *x_next - (*x_next - *x_prev) / ( g(x_next, alpha) - g(x_prev, alpha) ) * g(x_next, alpha);
*x_prev = aux;
}

/* Criterios a utilizar para parar
*
* Se pide una funcion que devuelva 1 para seguir o 0 para parar.
* Tambien puede imprimir opcionalmente el resultado
* int nombre_criterio(limite, x, alpha, iteraciones, tiempo, print_value)
*/

int iteraciones(double * limite, double x, double * alpha, int * iteraciones, double tiempo, int print_value) {
if (print_value) {
printf("%i iteraciones\n", *iteraciones);
}
if (*iteraciones < *limite) {
return 1;
} else {
return 0;
}
}

int absoluto(double * limite, double x, double * alpha, int * iteraciones, double tiempo, int print_value) {
double error = 1 / (x * x) - *alpha;
if (print_value) {
printf("%.99f error absoluto\n", error);
}
if (fabs(error) >= *limite) {
return 1;
} else {
return 0;
}
}

int relativo(double * limite, double x, double * alpha, int * iteraciones, double tiempo, int print_value) {
double error = ((1 / (x * x)) - *alpha) / *alpha;
if (print_value) {
printf("%.99f error relativo\n", error);
}
if (fabs(error) >= *limite) {
return 1;
} else {
return 0;
}
}

int tiempo(double * limite, double x, double * alpha, int * iteraciones, double tiempo, int print_value) {
double error = ((1 / (x * x)) - *alpha) / *alpha;
if (print_value) {
printf("%.99f tiempo\n", get_time());
}
if (get_time() <= *limite) {
return 1;
} else {
return 0;
}
}


int main (int argc, char * argv[]) {

// Me fijo que hayan dado un valor a calcular su raiz cuadrada
if (argc < 5 ) {
printf("Ejectuar ./tp1 <valor_de_alpha> <funcion> <metodo> <criterio_de_parada> <valor_de_fin_de_criterio> [x0 x1]\n");
printf("Funciones -> f: f(x), e: e(x)\n");
printf("Metodos -> n: newton, s: secante\n");
printf("Criterio de parada -> i: iteraciones, t: tiempo, r: error relativo, a: error absoluto\n");
exit(-1);
}

// Convierto <valor_de_alpha> a alpha
char * end;
double alpha = strtod(argv[1], &end);
if (argv[1] == end) {
printf("Error: El <valor_de_alpha> debe ser un double\n");
exit(-1);
}

printf("Buscando 1 / sqrt(%f)\n", alpha);

// Selecciono las funciones derivadas de e o f
double (*g)(double *, double *);
double (*g1)(double *, double *);
double (*g_end)(double *, double *);
if (strcmp(argv[2], "f") == 0) {
// utilizo g = f
g = f;
g1 = f1;
g_end = f_end;
printf("Utilizando f(x)\n");
} else if (strcmp(argv[2], "e") == 0) {
// utilizo g = e
g = e;
g1 = e1;
g_end = e_end;
printf("Utilizando e(x)\n");
} else {
printf("Error: El valor de <funcion> debe ser f o e\n");
exit(-1);
}

// Selecciono las funciones start e iter de newton o de secante
void (*start)(double *, double *, double *);
void (*iter)(double * x_prev, double * x_next, double * alpha, double (*g)(double *, double *), double (*g1)(double *, double *));
if (strcmp(argv[3], "n") == 0) {
// utilizo metodo = newton
start = newton_start;
iter = newton_iter;
printf("Utilizando Newton\n");
} else if (strcmp(argv[3], "s") == 0) {
// utilizo metodo = secante
start = secante_start;
iter = secante_iter;
printf("Utilizando Secante\n");
} else {
printf("Error: El valor de <metodo> debe ser n o s\n");
exit(-1);
}

// Selecciono los criterios de parada
int (*criterio)(double *, double, double *, int *, double, int);
if (strcmp(argv[4], "i") == 0) {
criterio = iteraciones;
printf("Criterio de parada iteraciones");
} else if (strcmp(argv[4], "a") == 0) {
criterio = absoluto;
printf("Criterio de parada error absoluto");
} else if (strcmp(argv[4], "r") == 0) {
criterio = relativo;
printf("Criterio de parada error relativo");
} else if (strcmp(argv[4], "t") == 0) {
criterio = tiempo;
printf("Criterio de parada tiempo");
} else {
printf("Error: El valor de <metodo> debe ser i, a, r o t\n");
exit(-1);
}
// Cargo el limite
double limite = strtod(argv[5], &end);
if (argv[5] == end) {
printf("Error: El <limite> debe ser un double\n");
exit(-1);
}
printf(" con limite %f\n", limite);

double x_prev = 1.1; // Mi x0 con el cual empiezo
double x_next = 2;
// Me fijo si uso las x_next y x_prev default o las que pidio el usuario
if (argc == 8 ) {
x_prev = strtod(argv[6], &end);
if (argv[6] == end) {
printf("Error: El <x0> debe ser un double\n");
exit(-1);
}
x_next = strtod(argv[7], &end);
if (argv[7] == end) {
printf("Error: El <x1> debe ser un double\n");
exit(-1);
}
} else {
// TODO: Inicializo x_prev y x_next
// Las funciones ahora no hacen nada
(*start)(&x_prev, &x_next, &alpha);
}

printf("Utilizando x0=%f y x1=%f\n", x_prev, x_next);

// Terminado el preambulo, linea en blanco
printf("\n");

int i = 0;


// Empiezo a contar el tiempo
init_time();

while ((*criterio)(&limite, (*g_end)(&x_next, &alpha), &alpha, &i, get_time(), 0) && i < MAX_ITER) {
(*iter)(&x_prev, &x_next, &alpha, g, g1);
printf("%.99f Iter\n", x_next);
i++;
}
double tiempo_total = get_time();

// Terminadas las iteraciones, linea en blanco
printf("\n");

printf("%.99f resultado\n", (*g_end)(&x_next, &alpha));
iteraciones(&limite, (*g_end)(&x_next, &alpha), &alpha, &i, tiempo_total, 1);
absoluto(&limite, (*g_end)(&x_next, &alpha), &alpha, &i, tiempo_total, 1);
relativo(&limite, (*g_end)(&x_next, &alpha), &alpha, &i, tiempo_total, 1);
tiempo(&limite, (*g_end)(&x_next, &alpha), &alpha, &i, tiempo_total, 1);

return 0;
}

0 comments on commit 12122e9

Please sign in to comment.