PrInf10: Bucles
| Práctica de Informática | |
|---|---|
| Bucles con for | |
| Práctica anterior | Siguiente práctica |
| Este artículo es un guión de prácticas de Informática | |
En esta práctica vamos a conocer una estructura de programación nueva, que no hemos usado hasta ahora. Se trata del concepto de bucles, que sirven para repetir un conjunto de comandos varias veces. Existen muchas situaciones en las que es útil repetir un conjunto de comandos sin tener que escribirlos varias veces. Por ejemplo, muchos métodos numéricos realizan aproximaciones sucesivas a la solución, repitiendo los mismo comandos, pero con valores que se van actualizando en cada aproximación. La implementación de este tipo de cálculos requiere el uso de bucles.
Contenido
1 Requisitos previos
Es muy recomendable haber completado satisfactoriamente todas las prácticas anteriores antes de empezar con esta práctica.
El contenido de esta práctica se explica en el siguiente vídeo. Puede ser recomendable visualizar el vídeo antes de realizar esta práctica:
2 Comandos que se aprenderán en esta práctica
En esta práctica vamos a ver qué significan los siguientes comandos de MATLAB / Octave
| for | sqrt |
3 Contenido de la práctica
Como ejemplo para esta práctica vamos a implementar un método numérico para aproximar raíces cuadradas. En Octave UPM ya tenemos un comando que calcula raíces cuadradas, el comando sqrt; nosotros usamos este método como ejemplo para ilustrar qué es un bucle porque es un método sencillo y muy ilustrativo. Obviamente, en situaciones reales, no usaríamos un método propio para calcular la raíz cuadrada, y usaríamos el comando sqrt, que probablemente funcione mucho mejor que el método que vamos a implementar.
3.1 Descripción del método numérico
Existen muchos métodos para aproximar raíces cuadradas. En esta práctica vamos a usar el método babilonio, que aproxima el valor de la raíz transformando sucesivamente un rectángulo en un cuadrado. Cuantas más aproximaciones hagamos, más cercano al cuadrado estaré el rectángulo, y más cercano estará el lado del cuadrado al valor de la raíz cuadrada. El proceso aparece ilustrado en la figura de la derecha.
Supongamos que queremos calcular el valor de la raíz cuadrada de [math]A[/math]. Inicialmente, dibujamos un rectángulo de área [math]A[/math], pero seleccionamos la altura de manera que sea igual a 1 (es decir, [math]W=1[/math] en la figura de la derecha). Por tanto, inicialmente tendremos que [math]L=A[/math], ya que [math]A = L\cdot W[/math].
El valor de [math]\sqrt{A}[/math] tiene que estar entre [math]1[/math] y [math]A[/math]. Por ejemplo, la raíz de [math]10[/math] es [math]3.16 \in [1,10][/math]. Por tanto, el valor [math]\sqrt{A}[/math] estará inicialmente entre [math]L[/math] y [math]W[/math].
En el siguiente paso, vamos a achatar el rectángulo, haciendo su forma más cuadrada usando un valor medio del lado. Es decir, [math]\displaystyle L_1=\frac{L+W}{2}[/math]. Como el área del rectángulo no puede cambiar, nos queda que [math]\displaystyle W_1=\frac{A}{L_1}[/math]. Si hubiéramos partido de este rectángulo inicialmente, tendríamos que el valor de la raíz cuadrada estaría entre los valores de los lados del rectángulo, igual que en el primer rectángulo que hemos usado. Es decir, [math]\sqrt{A} \in [W_1, L_1][/math]. Si repetimos este proceso varias veces, el rectángulo se convertirá cada vez más en un cuadrado, y los valores de [math]W_1[/math] y [math]L_1[/math] estarán más cercanos entre sí y más cercanos al valor de [math]\sqrt{A}[/math].
Vamos a ver este proceso en código. Como todos los programas, vamos a dividirlo en tres partes: entrada, algoritmo y salida. En este caso, la entrada de datos consiste en el valor cuya raíz queremos calcular:
% Entrada de datos
A = input('Introduce el numero cuya raiz quieres calcular: ');El siguiente paso será el algoritmo. Como hemos dicho, partimos de un rectángulo con [math]W=1[/math], y hacemos una aproximación tomando el valor medio:
% Algoritmo
% Rectangulo inicial
W = 1;
L = A;
% Primera aproximacion
L1 = (L+W)/2;
W1 = A/L1;Una vez que hemos realizado la aproximación, podemos mostrar ya el resultado en pantalla. En este caso, tomamos [math]L_1[/math] como el valor aproximado de la raíz:
% Salida de datos
fprintf('La raiz de %.4f es %.4f\n', A, L1);Es decir, el programa completo quedaría como sigue
% Entrada de datos
A = input('Introduce el numero cuya raiz quieres calcular: ');
% Algoritmo
% Rectangulo inicial
W = 1;
L = A;
% Primera aproximacion
L1 = (L+W)/2;
W1 = A/L1;
% Salida de datos
fprintf('La raiz de %.4f es %.4f\n', A, L1);
Podemos probar este programa para calcular [math]\sqrt{10}[/math], que hemos visto que era igual a [math]3.16[/math]
Introduce el numero cuya raiz quieres calcular: 10 La raiz de 10.0000 es 5.5000
| |
Tarea: | Escribe el programa anterior en Octave UPM y comprueba que obtienes el mismo resultado al calcular la raíz de 10 |
Como podemos ver, la aproximación es muy mala. Podemos remediarlo escribiendo varias aproximaciones seguidas. Además, ya que los valores intermedios de la aproximación [math]L_1[/math] y [math]W_1[/math] solo se usan al final, podemos reutilizar continuamente las mismas variables. Si hacemos cuatro aproximaciones, el programa quedaría como sigue:
% Entrada de datos
A = input('Introduce el numero cuya raiz quieres calcular: ');
% Algoritmo
% Rectangulo inicial
W = 1;L = A;
% Cuatro aproximaciones
L = (L+W)/2;
W = A/L;
L = (L+W)/2;
W = A/L;
L = (L+W)/2;
W = A/L;
L = (L+W)/2;
W = A/L;
% Salida de datos
fprintf('La raiz de %.4f es %.4f\n', A, L);
Si volvemos a probar el programa, ahora la aproximación es bastante mejor
Introduce el numero cuya raiz quieres calcular: 10 La raiz de 10.0000 es 3.1625
Sin embargo, si probamos a calcular [math]\sqrt{1000}[/math], cuyo valor es [math]31.62[/math], obtenemos el siguiente resultado
Introduce el numero cuya raiz quieres calcular: 1000 La raiz de 1000.0000 es 67.7253
¿Cómo podemos obtener una solución mejor? Ejecutando más aproximaciones. Sin embargo, esto requiere escribir muchas veces los mismos comandos. Si quisiéramos cambiar el número de veces que se ejecutan las aproximaciones, deberíamos modificar el programa para añadir o eliminar comandos. Esta solución no es admisible en programación. En cualquier situación donde nos veamos realizando una tarea repetitiva, y donde hubiera que modificar el programa para cambiar el número de veces que se ejecutan unos comandos, tenemos que tener claro que existe una alternativa de programación para que esas tareas las realice el ordenador. Un ordenador es muy eficiente realizando tareas repetitivas, y no puede pensar. Las personas funcionamos al contrario: somos capaces de pensar, pero somos muy malos realizando tareas muy repetitivas.
Para realizar tareas repetitivas en programación se usa una estructura conocida como bucle. Existen dos tipos principales de bucles:
- Bucles for
- Bucles while
En un bucle for tenemos que saber a priori cuántas veces hay que repetir un conjunto de comandos. Se suelen emplear, como veremos más adelante, para recorrer vectores y matrices, cuyas dimensiones son conocidas inicialmente.
Los bucles while se usan cuando conocemos la condición que tiene que cumplirse para repetir un conjunto de comandos. Mientras esa condición se cumpla, se repetirán los comandos. En muchas situaciones no podemos saber a priori cuántas veces hay que ejecutar un conjunto de comandos, pero sí podemos saber qué condición se cumple para que se sigan ejecutando. Por ejemplo, repetir unos comandos mientras el usuario no introduzca un número determinado por teclado. Sabemos que mientras no acierte el número tenemos que repetir los comandos, pero es imposible saber qué números va a introducir el usuario, y por tanto cuántas veces se ejecutará el bucle.
3.2 Ejemplo de ejecución
4 Comprobación de la práctica
Puedes comprobar si tu programa es correcto usando este programa: CompruebaPr09.m
Dale al botón derecho y elige guardar como. Cópialo en el mismo directorio donde hayas guardado la solución de la práctica. Luego puedes comprobar si tu programa es correcto escribiendo
CompruebaPr09('miSolucion');En este caso, la solución de la práctica está guardada en un fichero llamado miSolucion.m. Cambia el nombre al llamar a CompruebaPr09 si tu programa se llama diferente.
El programa no comprueba ninguna parte del programa desarrollada en alguna práctica anterior, solo comprueba si el mensaje se muestra cuando la temperatura está entre 0ºC y 100 ºC, o si se muestran los mensajes correspondientes cuando la temperatura está por debajo de 0 ºC o por encima de 100 ºC. Se probarán diferentes temperaturas, y se mostrará si el resultado es el esperado (mensaje que empieza por OK). Si en algún caso no es el esperado, mostrará un mensaje que empieza por WARN o por ERR.