Tema 7

Anuncio
Tema 7
Programación estructurada
Antes de comenzar a programar es preciso saber desarrollar algoritmos. Como se ha visto en el
tema anterior, un algoritmo es una descripción detallada de los pasos a seguir para resolver una
tarea. Los pasos han de ser operaciones capaces de ser llevadas a cabo por el operador al cual
va dirigido el algoritmo.
A fin de poder abordar problemas complejos es preciso aprender a diseñar correctamente
algoritmos y sus diagramas respetando las reglas de la programación estructurada. Para ello
se presentan en este tema una serie de algoritmos básicos los cuales se han dividido en varios
grupos.
7.1
Fundamentos de la programación estructurada
Es difı́cil hacer un resumen de las ideas de la programación estructurada a lectores que no tienen
cierta experiencia en programación. Esto sucede porque la programación estructurada pretende
evitar cierto tipo de situaciones que aparecen en programas grandes y medianos, pero que no
se advierten en los ejemplos dados a principiantes. Una de estas situaciones es la siguiente: un
programador escribe un diagrama de flujo tal y como aparece en la parte derecha de la figura 7.1.
Transcurrido cierto tiempo, el mismo programador es requerido para realizar una modificación
en el mismo. Éste intenta modificar el diagrama, pero la tarea le resulta ardua. Analizando los
motivos por los que el trabajo no avanza con rapidez se puede observar que:
• Es difı́cil hallar el punto en el cual hay que eliminar un bloque o insertar uno nuevo, pues
todo está enmarañado.
• Incluso aunque el diagrama tuviera una mejor disposición gráfica, cuesta trabajo ver si
121
122
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
Figura 7.1: Diagrama de flujo estructurado (izquierda) y no estructurado (derecha).
una modificación de una parte dará resultados indeseables en otra, debido al gran número
de interconexiones que hay.
Y los problemas no acaban ahı́. Tras realizar los cambios, el programador deberá probar el
nuevo programa para comprobar su correcto funcionamiento. Cada vez que se detecte un error
deberá volver a repetir el tedioso proceso de modificación. Los problemas descritos no serı́an
tales si el programador hubiera podido escribir el diagrama de flujo de forma parecida a la de
la figura 7.1 (izquierda), en la que se aprecia que no existen cruces de lı́neas y que cada módulo
tiene una entrada y una salida. Sobre estos dos aspectos se insistirá más adelante, por ahora no
es necesario comentar más las ventajas que para cualquier proyecto supone el tener programas
legibles y comprensibles.
7.1.1
Flujo lineal
Los diagramas se dice que tienen flujo lineal cuando no existen conexiones de vuelta atrás o
laterales. El flujo lineal se puede conseguir restringiendo las uniones entre bloques constructivos
a estructuras de entrada única y salida única. Es decir, usando para la confección del diagrama
de flujo grupos de bloques a los cuales llega sólo una flecha y de los cuales parte sólo una flecha.
La secuencia, la selección entre alternativas y la iteración forman un conjunto suficiente de
módulos constructivos para describir cualquier algoritmo. Es decir, es posible siempre realizar
c MRA & JAAR
�
123
2010 DISA. ESI. US.
un diagrama de flujo que contiene sólo las estructuras citadas. En la figura 7.2 se tienen tales
estructuras; se puede ver que son de entrada única y salida única.
no
no
sí
cuerpo del bucle
pregunta
módulo 1
pregunta
sí
módulo 2
opción 1
opción 2
condición
cuerpo del bucle
sí
no
secuencia
disyunción
repetición con salida
en cola
repetición con salida
en cabeza
Figura 7.2: Construcciones o uniones de bloques permitidaspara programas estructurados.
Estas estructuras permitidas reciben los nombres que se indican a continuación. De izquierda
a derecha en la citada figura 7.2 se tiene un par de bloques formando una secuencia, una bifurcación y bloques articulados en una estructura disyuntiva, una bifurcación con conexión
hacia atrás formando un blucle o estructura repetitiva con salida en cola y, finalmente, una
bifurcación formando una estructura repetitiva con salida en cabeza.
En lo sucesivo se usarán estas estructuras (y ninguna otra) para realizar los diagramas
de flujo, pero antes de pasar a los ejemplos es preciso comentar cómo se va a producir la
descomposición del problema global en módulos.
7.1.2
Análisis descendente
En ocasiones se presenta la programación estructurada como un conjunto de reglas a seguir. En
realidad no hay una definición exacta de programación estructurada, por lo que las reglas son
sólo una aproximación. Una idea importante de la programación estructurada es el análisis
descendente o jerarquizado. Consiste éste en identificar las funciones o tareas a cumplir por
el programa desde un punto de vista global y proceder luego a descomponer estas funciones en
otras menores. Éstas a su vez se vuelven a descomponer en un proceso que termina cuando se
alcanza el nivel del lenguaje o código usado. De este modo, el diseño del programa se realiza
por niveles. Se comienza por el nivel más general y se termina por lo particular o concreto.
El resultado del análisis descendente es un conjunto de diagramas que describen el algoritmo
con un nivel de detalle creciente. En un primer nivel el diagrama de flujo puede tomar la forma
dada en la figura 7.3 en la parte superior. En un segundo nivel, cada uno de los módulos es
detallado en un diagrama aparte. El proceso continúa mientras existan bloques que necesiten
explicaciones adicionales.
124
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
Inicio
Lectura de datos
Cálculo de
resultados
Escritura de
resultados
Fin
Inicio de lectura
de datos
Inicio de cálculo
de resultados
Inicio de
escritura de
resultados
...
...
...
Fin de lectura de
datos
Fin de cálculo de
resultados
Fin de escritura
de resultados
Figura 7.3: El análisis descendente aplicado a la confección de diagramas de flujo.
c MRA & JAAR
�
125
2010 DISA. ESI. US.
Es importante que antes de pasar al siguiente nivel se compruebe la validez del diagrama
actual. Para ello se ha de comprobar que las construcciones utilizadas pertenecen al conjunto
de las estructuras permitidas.
7.2
Cálculos en secuencia
Los cálculos en secuencia no presentan dificultad alguna desde el punto de vista algorı́tmico.
Los diagramas de flujo resultantes son lineales, sin bifurcaciones ni ciclos o repeticiones, y por
tanto de fácil creación.
Un programa evoluciona de modo lineal cuando realiza toda la secuencia de instrucciones de
forma continua, sin saltos en la ejecución. Éste es el caso presentado en el ejemplo de la suma
de dos números (ver figura 7.4). La realización y representación en diagrama de flujo de estos
programas es muy simple.
Inicio
Leer a
Leer b
c
a+b
Escribir c
Fin
primer dato
segundo dato
resultado, suma de a
y b
a
b
Variable real
Variable real
c
Variable real
Figura 7.4: Diagrama de flujo de un algoritmo para sumar dos números.
7.2.1
Ejercicios
Se propone realizar el diagrama de flujo de algoritmos que resuelvan las tareas siguientes:
1. Leer dos valores reales p y q del teclado y escribir media aritmética.
2. Leer un valor real x del teclado. Calcular y escribir r = x2 − 2x3 .
126
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
3. Leer los coeficientes de un polinomio de grado tres de la forma P (x) = x3 + ax2 + bx + c.
Leer a continuación un cierto valor para la variable independiente x y calcular y escribir
y = P (x).
4. Convertir a radianes un valor de ángulo medido en grados sexagesimales.
5. Calcular y escribir la temperatura T que corresponde a un mol de gas ideal sometido
a una presión P cuando ocupa un volumen V . Se supone que los valores de P y V se
proporcionan por teclado.
7.3
Estructuras selectivas
Las disyunciones o estructuras selectivas se construyen mediante un bloque bifurcación conectado
dos módulos que después vuelven a unirse. En el interior de cada módulo puede haber otras
estructuras permitidas: secuencias, iteraciones, etc.
Las bifurcaciones permiten tomar un camino o su alternativa, permitiendo que el programa
discurra por uno de dos caminos posibles en función de condiciones. Un ejemplo muy simple es
el siguiente: leer un número real por teclado y escribir el valor absoluto del mismo. Una forma
de resolver el programa es mediante el diagrama de flujo de la figura 7.5. La idea es hacer que
la secuencia de ejecución pase por la escritura del número o del número cambiado de signo en
función de que sea positivo o negativo.
Nota importante: en este libro la palabra positivo se ha de entender como ”mayor que cero”
quiere esto decir que el número cero no forma parte del conjunto de los números positivos.
Inicio
Leer x
sí
no
¿ x < 0 ?
r
-x
r
Escribir
r
Fin
x
dato
x
Variable real
resultado, valor
absoluto de x
r
Variable real
Figura 7.5: Diagrama de flujo con ruptura de secuencia.
c MRA & JAAR
�
2010 DISA. ESI. US.
127
Las bifurcaciones se pueden encadenar para dar solución a situaciones más complejas. Por
ejemplo considérese la función: NC(x, y), con (x, y) ∈ IR2 �→ c ∈ {1, 2, 3, 4}. Esta función calcula
el número de cuadrante en que se encuentra el punto (x, y) de IR2 . Se desea desarrollar un
algoritmo que lea las coordenadas x e y de un punto del plano (suponiendo que x �= 0 y que
y �= 0) y calcule y escriba r =NC(x, y).
El diagrama de la figura 7.6 presenta una posible solución mediante el uso de bifurcaciones
en cascada.
Figura 7.6: Programa que escribe el cuadrante en el cual se sitúa el punto en el plano (x, y).
7.3.1
Ejercicios
Utilizando las ideas que se han presentado en los puntos anteriores desarrolle algoritmos que
den solución a los problemas siguientes:
1. Leer un número real x y calcular y escribir r =| x |3 .
2. Calcular el coste de una llamada telefónica que ha durado t minutos sabiendo que si t < 1
el coste es de 0.4 euros mientras que para duraciones superiores el coste es 0.4 + (t − 1)/4
euros.
3. Leer un número real del teclado. Calcular el valor de p sabiendo que si x está en el
intervalo (2, 8] el resultado p toma el valor uno, en caso contrario toma el valor cero.
Escribir posteriormente el valor de p.
4. Leer un valor x del teclado. Calcular y escribir el valor y = f (x) siendo f una función
definida a trozos del siguiente modo:
128
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
x
x ∈ [−1, 3)
x > 50
resto
f (x)
10 − x
1
0
5. Leer las componentes de un vector de IR2 (x e y). Calcule el valor de r que se define como
r =NC(x, y) si x �= 0, y �= 0 y r = 0 si x = 0 o si y = 0.
7.4
Estructuras cı́clicas
Muchos algoritmos requieren la repetición de operaciones cierto número de veces. Al conjunto de
operaciones que se repite se le llama cuerpo del proceso repetitivo. Un ciclo (o proceso repetitivo
o bucle) queda completamente definido por el cuerpo y la condición de parada o salida. Cada
vez que el programa en ejecución pasa por el cuerpo del bucle se dice que ha realizado una
iteración.
La estructura denominada proceso repetitivo o bucle permite plasmar en diagramas de flujo
este tipo de procesos. La bifurcación al final del bloque hace las veces de control de salida.
En ocasiones es conveniente poner el control de salida en la cabeza del bucle, de este modo se
puede salir del bucle sin haber realizado ninguna operación. Ambos tipos de proceso iterativos
se muestran en la figura 7.7.
no
cuerpo
condición
sí
condición
cuerpo
sí
no
Figura 7.7: Estructuras repetitivas con control de salida en la cola (diagrama de la izquierda) y
control de salida en la cabeza (diagrama de la derecha).
A modo de ejemplo considérese la tarea de construir un vector v de dimensión n de forma que
la componente k−ésima tenga el valor vk = k 2 − 4. Por ejemplo, para n = 2 el vector resulta ser
v = [−3, 0], para n = 3 se obtiene v = [−3, 0, 5]. El problema que se quiere resolver es calcular
las componentes de v para un valor concreto de la dimensión n que se proporcione. Dicho de
otro modo, el algoritmo tendrá que requerir un valor concreto de n y calcular las componentes
v1 a vn . Se supondrá que n es entero y positivo.
c MRA & JAAR
�
129
2010 DISA. ESI. US.
El diagrama de la figura 7.8 presenta una posible solución al problema haciendo uso de
una estructura repetitiva con salida en la cola. Es muy conveniente dedicar unos minutos a
comprobar que el algoritmo resuelve el problema. Para ello pruebe a seguir mediante cálculos
a mano los pasos indicados en el diagrama para n = 1, n = 2, n = 3. Una vez realizado este
ejercicio no le resultará difı́cil determinar que el algoritmo ha de funcionar necesariamente para
todo n > 0.
Inicio
Leer n
k
1
vk
k·k -4
k
no
Dato, dimensión de v
n
Resultado, vector v
v
k+1
¿ k > n ?
sí
Fin
Índice para recorrer v.
Variable auxiliar
Componente k-ésima de v
calculada mediante la
expresión k 2 -4
k
vk
Variable
entera
Variable
vector de
enteros
Variable
entera
Variable
entera
Figura 7.8: Construcción de un vector mediante proceso iterativo con salida en la cola.
En el diagrama de la figura 7.9 se muestra otro diagrama que utiliza un bucle con salida en
la cabeza. Compruebe también mediante pruebas a mano que este diagrama realiza la misma
tarea que el del ejemplo anterior.
Debido a la sencillez de este ejemplo puede parecer que ambas maneras de realizar una
estructura cı́clica son equivalentes de un modo trivial. Aunque es cierto que se puede pasar
de una a otra esto no siempre se logra con facilidad. Además hay que tener en cuenta que
algunos lenguajes de programación están orientados a usar una de ellas, por ejemplo en el caso
de MATLAB siempre se prefiere la comprobación de salida en cabeza.
El bloque constructivo llamado módulo puede usarse para mejorar el aspecto visual de los
diagramas de flujo. En particular si un diagrama consta de varias estructuras repetitivas puede
ser interesante dedicar un módulo a cada uno de ellos. Para ilustrar esta idea considere el
problema cuyo enunciado es ”Se ha de leer una lista de n números reales, siendo n un entero
que ha de leerse previamente. Posteriormente se escribirá la lista en orden inverso. Se supondrá
que n > 0”. La figura 7.10 muestra el diagrama de flujo de una posible solución. Dicho diagrama
incluye dos módulos que se detallan en diagramas separados. La tabla de objetos es única pues
130
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
Inicio
Leer n
k
1
sí
¿ k > n ?
no
vk
Dato, dimensión de v
n
Resultado, vector v
v
k·k -4
k
k+1
Fin
Índice para recorrer v.
Variable auxiliar
Componente k-ésima de v
calculada mediante la
expresión k 2 -4
k
vk
Variable
entera
Variable
vector de
enteros
Variable
entera
Variable
entera
Figura 7.9: Construcción de un vector mediante proceso iterativo con salida en cabeza.
los diagramas correspondientes a los módulos se interpretan como parte del diagrama general.
A todos los efectos se trata por tanto de un único diagrama con la particularidad de que algunas
partes (los módulos) se detallan de forma separada.
Puede verse que los módulos ayudan a comprender mejor el algoritmo. Cada parte del
diagrama puede abarcarse de un golpe de vista, facilitando su comprensión y el análisis de su
validez.
7.4.1
Ejercicios
Los siguientes ejercicios se pueden resolver con ayuda de estructuras cı́clicas. Utilice módulos en
aquellos casos en que el diagrama resultante sea demasiado largo. Recuerde que los diagramas
no pueden cortarse.
1. Leer las componentes de un vector de números reales de dimensión 10. Escribirlo luego en
la pantalla.
2. Leer un entero n supuesto n > 0 y un vector v ∈ IRn×1 , calcular y escribir el producto
escalar m = v t v, m ∈ IR, donde v t simboliza el vector transpuesto de v.
3. Leer n (suponiendo que es entero y > 0). Leer a continuación las n componentes de un
c MRA & JAAR
�
131
2010 DISA. ESI. US.
Inicio
Inicio de lectura de
vector v
k
Inicio de escritura
inversa de vector v
1
k
n
Leer n
no
Lectura de
vector v
no
¿ k ≤ n ?
¿ k ≥ 1 ?
sí
sí
Leer v k
k
Escritura
inversa de
vector v
Fin
Escribir
k+1
Fin de lectura de
vector v
k
vk
k-1
Fin de escritura
inversa de vector v
Dato, dimensión de v
n
Variable entera
Dato, vector v
v
Variable vector de n
reales
Índice para recorrer v
Variable auxiliar
k
Variable entera
Componente k-ésima de v
v k Variable real
Constante para dar valor
inicial y modificar k
1
Constante entera
Figura 7.10: Diagrama de flujo con módulos para el problema de la escritura inversa.
132
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
vector de números reales dimensión n. Calcular y escribir luego la media aritmética de sus
componentes.
4. Leer un número real x y otro entero z. Calcular y escribir y = xz suponiendo que z ≥ 0.
5. Leer n (suponiendo que es entero y ≥ 0). Calcular y escribir f = n!.
6. Leer n (suponiendo que es entero y > 0) y un vector de dimensión n. Calcular y escribir
la componente de mayor valor.
7. Leer n (suponiendo que es entero y > 0) y un vector de dimensión n. Calcular y escribir
la componente de mayor valor y su ı́ndice dentro del vector.
8. Leer n (suponiendo que es entero y mayor que uno). Construir un vector v ∈ IRn×1 tal
que vk = vk−1 /3 + 0.5 para k = 2, ..., n y siendo v1 = 1.
9. Leer n (suponiendo que es entero y mayor que dos). Construir un vector v ∈ IRn×1 tal que
sus componentes sean los términos de la sucesión de Fibonacci1 .
10. Se han medido las longitudes de tornillos procedentes de un mismo lote de fabricación.
Se han dispuesto en un vector v de dimensión n > 2. Se dispone de v y n. Diseñe un
algoritmo para�calcular la media y la varianza de las longitudes. La varianza se calcula
como var = n1 nk=1 (vk − µ)2 , siendo µ la media aritmética de las componentes de v.
7.5
Ciclos dobles
El cuerpo de una estructura repetitiva no es necesariamente un módulo simple sino que puede
contener otras estructuras. En el punto anterior se han expuesto diversos ejemplos en los cuales
el cuerpo contiene exclusivamente estructuras en secuencia. No existe ningún impedimento para
que el cuerpo contenga estructuras selectivas o incluso otros ciclos.
Cuando un ciclo contiene a otro se obtiene una estructura doblemente repetitiva2 . En cada
iteración del ciclo externo se realizan varias repeticiones del cuerpo del ciclo interno.
Las repeticiones dobles son especialmente apropiadas para trabajar con matrices A ∈ IRm×n .
En muchas situaciones es preciso recorrer los elementos de la matriz para realizar de este modo
la lectura, escritura o cualquier otro cálculo. Se plantea en estos casos el problema de considerar
todos los posibles elementos akj de la matriz. Conviene recordar que el elemento genérico akj
tiene dos subı́ndices: k (filas) y j (columnas) que varı́an en los intervalos: k = 1, 2, ..., m y
j = 1, 2, ..., n.
1
La sucesión de Fibonacci comienza con a1 = 1, a2 = 1 y posteriormente cada término ak es la suma de los
dos anteriores ak−1 + ak−2 para k > 2.
2
Llamada frecuentemente bucles anidados por ser estas palabras la traducción literal de nested loops.
c MRA & JAAR
�
133
2010 DISA. ESI. US.
Para trabajar con matrices se puede emplear un ciclo dentro de otro. Normalmente el ciclo
externo recorre el ı́ndice de filas y el interno el ı́ndice de columnas. En la figura 7.11 se presenta
un diagrama de flujo que puede utilizarse para recorrer la matriz.
iniciar k a 1
sí
¿ k > m ?
no
iniciar j a 1
sí
¿ j > n ?
no
Operar con el
elemento a kj
Incrementar j
Incrementar k
Figura 7.11: Diagrama de flujo que permite recorrer una matriz gracias a dos estructuras repetitivas.
7.5.1
Ejercicios
Los ejercicios que se proponen a continuación se pueden resolver con la estructura de esta figura
7.11 (aunque alguno de ellos puede resolverse con estructuras más simples).
1. Lectura/escritura de una matriz m × n. Se han de leer del teclado las dimensiones m y n
(suponga que son números enteros positivos). A continuación se han de leer los elementos
134
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
akj de una matriz A de m filas y n columnas. Finalmente se presentará en la pantalla la
matriz leı́da.
2. Construir una matriz A ∈ IRm×n cuyo elemento genérico akj viene dado por akj = k 2 − j.
3. Dada una matriz (se supone ya leı́da) A de dimensiones m × n, se quiere anular (poner a
cero) los elementos de su diagonal principal y escribir la matriz resultante.
4. Traza de una matriz. Dada una matriz cuadrada A ∈ IRn×n dada siendo n > 0 un entero
también dado se ha de diseñar un algoritmo que permita obtener la traza de A (suma de
los elementos de la diagonal).
5. Suma de matrices. Dadas (suponga que ya han sido leı́das) dos matrices A ∈ IRm×n y
B ∈ IRm×n se quiere calcular y escribir la matriz C obtenida como suma de las anteriores
C = A + B.
6. Matriz traspuesta. Dada una matriz A ∈ IRm×n calcular su traspuesta B = At .
7. Submatriz triangular. Dada una matriz A ∈ IRm×n se desea calcular otra matriz B ∈ IRm×n
cuyos elementos son todos cero excepto los de la submatriz triangular inferior que son
iguales a los elementos de igual posición de A. Es decir, los elementos que están por debajo de la diagonal principal de A se copian en B, el resto de elementos de B valen cero.
Se supone que tanto m como n son números enteros mayores que uno ya leı́dos.
8. Máximo de una matriz. Dada una matriz A ∈ IRm×n calcular el elemento mayor.
9. Máximo de cada fila. Dada una matriz A ∈ IRm×n con m > 1 y n > 1 dados se desea
calcular un vector v ∈ IRm cuya componente genérica vk es el mayor valor de la fila
k−ésima de A.
10. Crear matriz de ”1” y ”0” al tresbolillo.
7.6
Ejercicios temáticos
En este punto se presenta una serie de problemas que pueden ser resueltos con algoritmos que
combinan algunas de las estructuras explicadas en este tema.
7.6.1
Sucesiones y series
1. Se quiere construir y escribir un vector v de dimensión n cuyas componentes siguen la ley
vk = 3 · vk−1 − k para k ≥ 2. Tanto n como v1 son cantidades que han de leerse del teclado.
�
2. Dado n > 0 hallar la suma s = nk=1 1/k.
c MRA & JAAR
�
135
2010 DISA. ESI. US.
�
3. Se desea calcular la suma s = nk=1 1/ak siendo los valores ak los elementos de la sucesión
dada por ak = ak−1 + ak−2 para k > 2, con a1 = 1 y a2 = 1. El lı́mite n ha de leerse del
teclado y se supone mayor que dos.
�
4. Se desea calcular la suma s = nk=1 1/k m siendo m y n dos números enteros positivos que
se suponen dados.
5. Escriba los n primeros términos de la sucesión dada por an = (1 + n1 )n , siendo n un número
entero positivo dado.
7.6.2
Ordenaciones
1. Dado un vector v de dimensión n cuyas componentes son todas positivas o cero se desea
reordenar sus componentes de mayor a menor. Por ejemplo, si
v = [2 3 8 5 4]
el resultado ha de ser un nuevo vector:
w = [8 5 4 3 2]
2. Repetir el ejercicio anterior pero sin usar un vector auxiliar como w. El resultado que se
pretende conseguir es que el propio vector v tenga sus componentes ordenadas.
3. Igual que el anterior pero suponiendo que v contiene cantidades positivas y negativas, por
ejemplo:
v = [−7 3 8 − 9 5 4 0 − 1]
ha de dar como resultado el propio vector reordenado ası́:
v = [8 5 4 3 0 − 1 − 7 − 9]
4. Un fabricante de automóviles dispone de un modelo de vehı́culo en cinco colores. Para
saber la aceptación de cada color realiza una encuesta usando un programa en su ordenador
portátil. El programa ha de ayudarle a contar los votos de los encuestados. El encuestador
tecleará el número del color elegido (de uno a cinco) cada vez que pregunte a una persona
nueva. Cuando no quiera preguntar a nadie más introducirá el valor -1. En ese momento
el programa le indicará el número de votos que cada color ha obtenido. Posteriormente se
han de ordenar los colores según los resultados de la votación.
5. Se desea calcular la mediana de los valores contenidos en un vector T ∈ IRn . Si n es impar
la mediana es el valor central del vector ordenado, en caso contrario la mediana es la media
de los dos elementos que están más al centro. En ambos casos el paso previo para calcular
la mediana es ordenar el vector.
Un ejemplo con n par es T = [10 23 11 15]. La ordenación produce T o = [23 15 11 10]
y la mediana es (15 + 11)/2 = 13. Un ejemplo con n impar es T = [11.8 12 28 11.5 14].
136
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
En este caso la ordenación produce un nuevo vector T o = [11.5 11.8 12 14 28], de donde
se obtiene la mediana que es el valor central 12.
Puede comprobar con los ejemplos anteriores que la mediana no coincide con la media
aritmética.
7.6.3
Cálculos con enteros
Para poder diseñar los algoritmos que resuelven algunos de los problemas propuestos a continuación puede necesitar una función que elimine los decimales de números reales y obtener de
este modo números enteros. Esta función recibe el nombre de parte entera y puede denotarse
matemáticamente como ParteEntera(). De este modo x ← ParteEntera(3.14) es equivalente a
x ← 3.
1. Dado un número entero x mayor que uno se ha de escribir un uno si el número es par y
un cero en caso contrario.
2. Dados dos números enteros positivos p y q, p > q, se ha de escribir un uno si son divisibles
y cero si no lo son.
3. Dado un número entero x mayor que uno se ha de escribir la lista de sus divisores comprendidos en el intervalo (1, x).
4. Dado un número entero x mayor que uno se ha de escribir un uno si es primo y un cero en
caso contrario. Para ello ha de comprobar si x es divisible por algún entero en el intervalo
(1, x).
5. Dada una cantidad N > 1 calcular la raı́z cuadrada entera aproximada r. Se ha de cumplir
que r · r ≤ N < (r + 1) · (r + 1).
Por ejemplo, si N = 24 se tiene que r = 4 pues 4 · 4 = 16 ≤ 24 < 25 = 5 · 5.
6. Se ha de escribir un uno en el caso de que exista un trı́o (x, y, z)de números enteros positivos
tales que x2 + y 2 = z 2 . Limite la búsqueda a x ∈ (0, 100], y ∈ (0, 100]. En caso de que no
se encuentre solución se ha de escribir un cero.
7. Repita el ejercicio anterior pero escribiendo todas las soluciones que encuentre en el intervalo x ∈ (0, 1000], y ∈ (0, 1000].
8. Dados dos números enteros positivos p y q escriba un algoritmo que permita hallar el
máximo común divisor de los mismos.
9. Como aplicación del ejercicio anterior diseñe un algoritmo que permita descubrir si dos
enteros positivos son primos entre sı́, es decir si su máximo común divisor es uno.
c MRA & JAAR
�
7.6.4
2010 DISA. ESI. US.
137
Matrices
1. Multiplicación de matrices. Suponga ya leı́das A ∈ IRm×n y B ∈ IRn×p , calcule C = A · B.
2. Matriz al cubo. Diseñe un algoritmo que permita obtener B = A3 , siendo A ∈ IRn×n una
matriz cuadrada que se supone ya leı́da.
3. Exponenciación de matrices. Diseñe un algoritmo que permita obtener B = Ap , siendo
A ∈ IRn×n una matriz dada y p > 0 un entero también dado.
4. Dados dos enteros positivos m�
y n se desea construir la matriz S ∈ IRm×n cuyo elemento
genérico viene dado por skj = kh=1 1/hj
7.6.5
Leyes
La evolución de ciertas magnitudes del mundo real puede en ocasiones acomodarse a simples
leyes expresables de un modo similar a las sucesiones. En este apartado se proporcionan algunos
ejemplos que ilustran la forma en que el cálculo por ordenador ayuda a la Ciencia y la Ingenierı́a.
1. La cantidad de un cierto isótopo radioactivo presente en una mezcla varı́a con el tiempo
pues el isótopo se descompone emitiendo radiación. Se denota mediante y(k) la cantidad
en gramos de isótopo en el instante de tiempo t = k medido en años. Unos cientı́ficos han
descubierto que se cumple que y(k) = 0.99 · y(k − 1). Si un barril de desechos radioactivos
contiene 1000 gramos de isótopo, ¿cuál será la cantidad de isótopo presente al cabo de 500
años?
2. La velocidad de un paracaidista en su descenso al suelo una vez que ha abierto el paracaı́das
se denota mediante v(k) (m/s), siendo k el tiempo que lleva cayendo medido en segundos,
k > 1. Se ha especulado con la idea de que dicha velocidad sigue la ley: v(k) = v(k −
1) + 10 − 0.4(v(k − 1))2 . Sabiendo que una caı́da tı́pica puede durar 5 minutos y que
el paracaı́das se suele abrir con una velocidad de 100 Km/h, ¿con qué velocidad llega al
suelo?
3. Se sabe que la cantidad de bacterias de cierta especie en un cultivo es x(k) = 1.1x(k −
1) siendo k el tiempo medido en horas, k > 1. Si al cabo de la primera hora x(1) se
contabilizaron 100 unidades, ¿cuántas habrá al cabo de un dı́a?
7.7
Comprobación del funcionamiento de algoritmos
La comprobación del buen funcionamiento de un algoritmo es una tarea difı́cil y para la cual
no existen reglas generales. En muchos casos sin embargo el sentido común y el razonamiento
138
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
lógico permiten realizar pruebas que permiten asegurar la corrección.
Existen dos formas de enfrentarse a la tarea de decidir si un algoritmo dado es verdaderamente una solución al problema planteado: la prueba del algoritmo con un conjunto de datos
controlado y la prueba mediante razonamiento lógico-matemático.
7.7.1
Pruebas con datos controlados
La prueba del algoritmo con datos controlados consiste en preparar una serie de valores de los
datos para los cuales se conoce el resultado correcto. Posteriormente se siguen los pasos del
algoritmo y se comprueba si los resultados que el algoritmo produce coinciden con los resultados
conocidos de antemano.
Como ejemplo considere el problema de escribir un uno en caso de que cierto entero x sea
primo y cero en otro caso. Si se desea comprobar si cierto algoritmo A es correcto puede ser
buena idea probar A con x = 2 y comprobar que el resultado es que se escribe un uno. Si el
resultado no es este no hace falta comprobar más, pues un solo fallo sirve para invalidar A. Si
el resultado es correcto se puede pasar a probar A con x = 3 y repetir el proceso.
Es fácil ver que este método tiene el grave inconveniente de que hacen falta tantas pruebas
como posibles valores distintos puede tomar el dato x. En muchas ocasiones se recurre al método
de probar el algoritmo sólo en algunos valores elegidos. Por ejemplo con varios números primos
y otros no primos tanto grandes como pequeños. Hay que resaltar que este tipo de pruebas
no permite validar el algoritmo completamente. Esto es ası́ porque un algoritmo puede dar
resultados correctos en muchas situaciones y sin embargo no ser correcto universalmente pues
puede que contenga errores que no se han manifestado con esos datos.
No existe un procedimiento general para seleccionar valores de prueba para algoritmos, sin
embargo es posible dar algunos consejos como:
• probar valores particulares que puedan dar problemas como el cero (en el caso de que haya
divisiones), o los números negativos (si hay raı́ces cuadradas).
• probar los valores extremos de los datos, por ejemplo si se sabe que el dato x ∈ IR cumple
que x ∈ [5, 3] entonces merece la pena probar con los valores x = 3 y x = 5.
7.7.2
Razonamientos por inducción
En muchos casos es posible aplicar el método matemático de prueba inductiva. Por ejemplo
cuando el dato de un algoritmo puede tomar cualquier valor n ∈ IN.
c MRA & JAAR
�
2010 DISA. ESI. US.
139
El razonamiento inductivo se lleva a cabo probando (en el sentido matemático) que si el
algoritmo funciona para un valor n cualquiera entonces debe funcionar también para el valor
siguiente n + 1. La prueba se completa utilizando el algoritmo con n = 1 y comprobando
que el resultado es satisfactorio. Mediante inducción se obtiene que entonces el algoritmo debe
funcionar correctamente para n = 2 y de aquı́ que también sea correcto para n = 3, etc.
Este tipo de razonamiento permite decidir la corrección de algoritmos que contienen estructuras iterativas. En estos casos los puntos que causan mayores problemas son las entradas y
salidas de los ciclos de repetición. Por este motivo hay que prestar mucha atención a los valores
iniciales asignados a ı́ndices y contadores antes de entrar en el ciclo, a la actualización de los
mismos dentro del cuerpo que se repite y finalmente a la condición de salida del ciclo.
El principal inconveniente de este método de corrección es que es posible que la prueba
matemática contenga errores, proporcionando como resultado que se etiquete como correcto un
algoritmo que no lo es. Por este motivo es conveniente siempre realizar la prueba por ambos
métodos.
7.7.3
Modularidad
Si el diseño del algoritmo se ha llevado a cabo de forma adecuada el diagrama ha de consistir
en una serie de módulos (o funciones) de pequeño tamaño que se unen para formar módulos
mayores.
El análisis de algoritmos se realiza entonces de una forma cómoda pues basta con probar
cada módulo de forma independiente. Cuando se han comprobado los módulos de un cierto
nivel puede pasarse al nivel superior. Las comprobaciones de un nivel superior pueden llevarse
a cabo sin necesidad de volver a utilizar o analizar los módulos de niveles inferiores. En lugar
de ello es posible sustituir mentalmente dichos módulos por mecanismos que automáticamente
proporcionan los resultados correctos. De este modo el análisis se lleva a cabo de forma jerárquica
lo cual permite avanzar con mayor rapidez y confianza.
7.8
Análisis de la estructura
Es posible ahora poner un par de ejemplos para aclarar las ideas sobre la programación estructurada. Considere en primer lugar el diagrama que aparece en la parte izquierda de la figura
7.12. A la vista cómo están unidos los bloques ¿sabrı́a decir si es un diagrama bien estructurado?.
Para responder a esta cuestión resulta conveniente agrupar los bloques que forman secuencias
en módulos, de forma que la estructura subyacente quede expuesta con mayor claridad. Esto
140
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
se ha realizado en el diagrama del centro. Finalmente, en el diagrama de la derecha se han
sustituido las secuencias por módulos, quedando al descubierto una estructura que coincide con
una de las estructuras permitidas (véase de nuevo la figura 7.2). Esta estructura es un bucle con
salida en cola y aparece aquı́ combinado en secuencia por arriba y abajo con otros dos módulos.
Figura 7.12: Análisis de la estructura de un diagrama.
Este sencillo análisis permite determinar que la estructura del diagrama está de acuerdo con
las normas establecidas en este capı́tulo. Observe que para discutir sobre la estructura de un
diagrama no es preciso conocer las operaciones que se realizan en cada bloque. En efecto, la
estructura depende exclusivamente de las uniones entre bloques y no de su contenido.
Considere ahora el diagrama que se muestra en la parte izquierda de la figura 7.13. A primera
vista no parece haber nada que indique que el diagrama no sea estructurado (al menos no lo
parece para el principiante en esta materia). En la parte central y derecha de la figura se pone de
manifiesto que esto es un error. En efecto, el recuadro a trazos intenta encerrar una estructura
del tipo repetición o bucle con salida en cola. Sin embargo el recuadro no tiene solamente una
entrada y una salida como se requiere. De hecho, el recuadro es cortado por dos flechas de
entrada y por una de salida. Si uno intenta encerrar la estructura inferior mediante un recuadro
(véase parte derecha de la figura) ocurre nuevamente que no se cumple la regla de una única
entrada y una única salida. En este caso hay dos salidas y una sola entrada.
c MRA & JAAR
�
2010 DISA. ESI. US.
Figura 7.13: Análisis de la estructura de un diagrama.
141
142
TEMA 7. PROGRAMACIÓN ESTRUCTURADA
Descargar