\endverbatim
\section resolucion Resolución.
- El \ref main "programa principal" se divide en FIXME N tareas principales,
+ El \ref main "programa principal" se divide en 3 tareas principales,
cada una realizada por una función particular.
\subsection obtencion Obtención y validación de parámetros del usuario.
Antes de comenzar a hacer cálculos es necesario obtener los valores de
las \ref variables "variables" de la entrada del usuario (en este caso
- a través de parámetros de línea de comandos). Esto es realizado
+ a través de parámetros de línea de comandos). Esta tarea es realizada
por la función cargar_datos().
\subsection integracion Integración de la ecuación diferencial.
función y almacenándolos en el \ref Resultados "vector de resultados",
tarea realizada por la función calcular().
+ \subsection impresion Impresión del gráfico por pantalla.
+ Finalmente todo lo que queda es graficar por pantalla el resultado de la
+ función. Para esto se va imprimiendo línea por línea, chequeando qué
+ punto de la función cae en cada rango de valores representados por una
+ línea. Esta tarea es realizada por la función resultados_graficar().
+
+\section conclusiones Conclusiones.
+ Realmente no se me presentaron muchos problemas para resolver el TP. El
+ único problema que tuve fue realizando el \ref impresion "gráfico", en
+ ciertas circunstancias (por problemas de redondeo) el valor máximo de la
+ función no era graficado. Esto se solucionó incluyendo una línea más al
+ gráico, con el rango que va desde el máximo de la función (en realidad desde
+ el mínimo más 20 pasos verticales) hasta el máximo más un paso vertical.
+ Es por esto que en realidad se grafican 21 pasos. Podría haber graficado 20
+ pasos pero el código quedaría menos claro (o tendría que poner la constante
+ \ref ALTO en 19 en vez de 20).
+
+ Otro detalle que cabe ser mencionado es que para valores altos del
+ \ref variables "step" (mayores a 30), la solución se vuelve inestable.
+
*/
return FALSE;
}
/* TODO Verificar que el paso no sea cero y que tf > ti. */
- /* XXX - sacar */
- printf("paso = %f, tf = %f, f0 = %f\n", *paso, *tf, *f0);
return TRUE;
}
/* Itero paso a paso calculando el valor de la función. */
for (i = 1; i < pasos; i++) {
/* f(t+paso) = FUNCION(paso, f(t)) */
- (*res)[i] = FUNCION(paso, (*res)[i-1]);
- /* FIXME sacar!!!! */
- printf("i = %i, t = %.2f, f(t) = %.2f\n", i, (Real)i * paso, (*res)[i]);
+ (*res)[i] = FUNCION(paso, (*res)[i-1]);
}
return pasos;
}
-Real max(const Resultados* res, size_t pasos) {
- size_t i;
- Real max = (*res)[0];
+Real resultados_max(Resultados* res, size_t pasos) {
+ size_t i;
+ Real max = (*res)[0];
for (i = 1; i < pasos; i++) {
if ((*res)[i] > max) {
max = (*res)[i];
return max;
}
-Real min(const Resultados* res, size_t pasos) {
- size_t i;
- Real min = (*res)[0];
+Real resultados_min(Resultados* res, size_t pasos) {
+ size_t i;
+ Real min = (*res)[0];
for (i = 1; i < pasos; i++) {
if ((*res)[i] < min) {
min = (*res)[i];
return min;
}
+void inicializar_linea(char* linea, char caracter, size_t cant) {
+ size_t j;
+ for (j = 0; j < cant; j++) {
+ linea[j] = caracter;
+ }
+ linea[cant] = '\0';
+}
+
+void resultados_graficar(Resultados* res, size_t pasos, char punto, char blanco) {
+ /* Máximo valor de la función. */
+ Real min;
+ /* Mínimo valor de la función. */
+ Real max;
+ /* Paso utilizado para la representación de las líneasMínimo valor de la función. */
+ Real pasoh;
+ int i;
+ int j;
+ char linea[ANCHO];
+ min = resultados_min(res, pasos);
+ max = resultados_max(res, pasos);
+ pasoh = (max - min) / (ALTO);
+ printf("min: %f, max: %f, pasoh: %f\n", min, max, pasoh);
+ /* Inicializa la línea. */
+ inicializar_linea(linea, blanco, MAX_PASOS);
+ /* Por cada línea a dibujar. */
+ for (i = ALTO; i >= 0; i--) {
+ /* Se fija si hay algún punto que entre en el rango. */
+ for (j = 0; j < pasos; j++) {
+ /* Si está entre en el rango a imprimir, se agrega un punto. */
+ if (((min + pasoh * i) <= (*res)[j])
+ && ((*res)[j] < (min + pasoh * (i + 1)))) {
+ linea[j] = punto;
+ /* Si no, se lo deja en blanco. */
+ } else {
+ linea[j] = blanco;
+ }
+ }
+ printf("%8.2f _%s\n", min + pasoh * i, linea);
+ }
+}
+
int main(int argc, const char** argv) {
/* TODO: Declaración de variables. */
Resultados resultados;
size_t pasos;
- Real paso = DEFAULT_PASO;
- Real tf = DEFAULT_TF;
- Real f0 = DEFAULT_F0;
+ Real paso = DEFAULT_PASO;
+ Real tf = DEFAULT_TF;
+ Real f0 = DEFAULT_F0;
+ char punto = '*';
+ char blanco = ' ';
/* Obtención de datos. */
if (!cargar_datos(argc, argv, &paso, &tf, &f0)) {
/* Cálculo de la solución, dejando en un array los valores de cada paso. */
pasos = calcular(&resultados, paso, T0, tf, f0);
+ /* XXX - sacar o poner más lindo. */
+ printf("paso = %f, tf = %f, f0 = %f, pasos = %i\n", paso, tf, f0, pasos);
/* TODO: Barrido de pantalla de arriba hacia abajo consultando el array
* y dibujando los resultados pertinentes. */
- /* TODO: Liberación de memoria y otras limpiezas, en caso de ser necesario. */
+ resultados_graficar(&resultados, pasos, punto, blanco);
+
return EXIT_SUCCESS;
}
/** Altura (en líneas) utilizadas para dibujar el gráfico. */
#define ALTO 20
+/** Ancho (en líneas) utilizadas para dibujar el gráfico. */
+#define ANCHO 70
+
/** Tiempo inicial. */
#define T0 0.0
* pérdida de velocidad que agrega la indirección de un llamado a una
* función.
*/
-#define FUNCION(paso, ft) ((ft) + (500.0 - (ft)) / 30.0 * paso)
+#define FUNCION(paso, ft) ((ft) + ((500.0 - (ft)) / 30.0) * paso)
int argtod(const char* arg, Real* var, const char* nom);
/**
- * Carga los datos necesarios por el programai.
+ * Carga los datos necesarios por el \ref main "programa".
* Obtiene los datos desde los parámetros de la línea de comandos, validándolos
* y mostrando un mensaje de error en caso de haberlo.
*
* \param f0 Valor inicial de la función.
*
* \return TRUE si se cargaron bien, FALSE si no.
- * \todo Verificar que el paso no sea cero y que tf > ti.
+ * \todo \b TODO Verificar que el paso no sea cero y que tf > ti.
+ * \todo \b TODO Agregar opciones para especificar caracter en blanco y de punto.
*/
int cargar_datos(int argc, const char** argv, Real* paso, Real* tf, Real* f0);
*
* \return Máximo resultado.
*/
-Real max(const Resultados* res, size_t pasos);
+Real resultados_max(Resultados* res, size_t pasos);
/**
* Devuelve el valor mínimo de los resultados.
*
* \return Mínimo resultado.
*/
-Real min(const Resultados* res, size_t pasos);
+Real resultados_min(Resultados* res, size_t pasos);
+
+/**
+ * Rellena una cadena de caracteres con un caracter arbitrario.
+ *
+ * \param linea Cadena de caracteres.
+ * \param caracter Caracter utilizado para rellenar.
+ * \param cant Cantidad de caracteres a rellenar.
+ */
+void inicializar_linea(char* linea, char caracter, size_t cant);
+
+/**
+ * Imprime un gráfico de los resultados por pantalla.
+ * Realiza un gráfico de la función por pantalla, imprimiendo línea por línea.
+ * Cada línea representa un rango de valores. En cada línea se dibuja el
+ * caracter \e punto si la función en el tiempo evaluado está en el rango de esa
+ * línea. Si no lo está se dibuja el caracter \e blanco.
+ *
+ * \param res Vector de resultados a graficar.
+ * \param pasos Cantidad de pasos a graficar.
+ * \param punto Caracter utilizado para dibujar un punto de la función.
+ * \param blanco Caracter utilizado para dibujar un punto en blanco.
+ */
+void resultados_graficar(Resultados* res, size_t pasos, char punto, char blanco);
/**
* Programa principal.