0:05
En esta segunda lección os vamos a resumir los conceptos
más importantes relacionados con la representación de algoritmos en
pseudocódigo, centrándonos en las principales
acciones y estructuras de control
que debemos conocer para seguir el curso de sistemas digitales.
La especificación de sistemas digitales mediante algoritmos es
uno de los aspectos centrales de nuestro curso.
Muchas veces para poder definir algoritmos, vamos a utilizar secuencias de
instrucciones muy similares a las
instrucciones de los lenguajes de programación.
Si ya conocéis otros lenguajes, por ejemplo C, Java,
etcétera, el contenido de este tema os resultará muy familiar.
¿Cómo se define un algoritmo?
Es un procedimiento no ambiguo que resuelve un
problema, nos indica una secuencia de
operaciones a realizar para conseguir el resultado
deseado, como por ejemplo, un cálculo
complejo, el control de algún proceso, etc.
El algoritmo es independiente del lenguaje de programación que se utilizará.
Para poder representar los algoritmos existen diferentes alternativas,
el lenguaje natural, el pseudocódigo, los diagramas de flujo
y los lenguajes de programación. ¿Qué se entiende por pseudocódigo?
Es una forma de descripción informal de un algoritmo
con una sintaxis cercana a los lenguajes de programación.
El pseudocódigo nos permite describir un
algoritmo utilizando una mezcla de frases en
lenguaje común, instrucciones de programación y
palabras clave que definen las estructuras básicas.
Aquí presentamos un resumen de las principales acciones y estructuras
de control que podemos utilizar
cuando describimos un algoritmo mediante pseudocódigo.
Comenzaremos definiendo las asignaciones, los operadores, entre los que
destacaremos los de comparación, los lógicos y los operadores aritméticos.
Las estructuras de control que
utilizaremos principalmente son las estructuras de
selección y estructuras de iteración.
Y finalmente definiremos el concepto de procedimiento o sub-rutina.
Asignaciones.
La acción denominada asignación nos permite
almacenar un valor en una variable.
Se representa por este símbolo.
El valor puede ser una constante o
el resultado de la evaluación de una expresión.
Primero se evalua siempre la expresión de la derecha para asignarla a
la variable que tenemos en la izquierda, por ejemplo, en este caso tenemos la
asignación de 3 al valor X, 2 al valor Y, y 1 al valor Z.
En la siguiente asignación, el valor Y que recibe será 2 por X, por
tanto 2 por 3, más Y, que será el valor 2, más Z que vale 1.
Por tanto,
estamos asignando a la variable Y el valor 9.
Operadores.
En las descripciones en pseudocódigo, podemos encontrarnos
operadores de tipo comparación, aritméticos y lógicos.
Los principales operadores de comparación son "menor que", "mayor que",
"igual que", "menor o igual que", que lo podemos representar con este símbolo
o con este otro, "mayor o igual que", y el símbolo "diferente".
Aritméticos.
Podemos encontrarnos cuatro tipos, el operador
"suma", el operador "resta", "producto" y "división".
Finalmente dentro de los operadores del tipo lógico, destacaremos el operador
"suma lógica", "producto lógico" y "negación". Vamos a proponer un ejercicio.
Si tenemos la siguiente descripción en pseudocódigo, ¿Qué valor
tendrá la variable X después de la línea 4?
¿Qué valor tendrá la variable Z después de la línea 5?
Y ¿qué valor tendrá la variable Y después de la línea 6?
Vamos a resolver el ejercicio propuesto.
Si tenemos la siguiente descripción en pseudocódigo, ¿Qué valor tendrá
la variable X después de la línea 4?
Después de la línea 4 hemos asignado a la variable X el valor
2 y a la variable Y el valor 3, por tanto cuando lleguemos a
la línea 4, la variable X recibirá la asignación de X, que valía
2, por 3, por tanto el valor que tendrá la variable X será 6.
¿Qué valor tendrá la variable Z después
de la línea 5?
En este caso la variable Z está recibiendo el valor X que lo acabamos
de actualizar a 6 y le estamos sumando el valor de Y que valía 3.
Por tanto la variable Z está recibiendo el valor 9.
Por último, ¿qué valor tendrá la variable Y después de la línea 6?
En este caso la variable Y está recibiendo el valor de X que
lo hemos actualizado a seis, el valor de Y que vale 3, y el valor de Z que vale
9, por tanto el valor final será 18. Estructuras de control.
Las acciones que podemos describir mediante pseudocódigo se organizan
en bloques de acciones que siguen unas estructuras básicas.
Las estructuras de selección y las estructuras de iteración.
Dentro de las estructuras de selección
veremos las estructuras simple, doble y múltiple.
Dentro de las estructuras de iteración veremos While y For.
Estructuras de selección o decisión.
Las estructuras de selección nos permiten tomar decisiones condicionadas
a la evaluación de una expresión, normalmente una condición lógica.
Veremos la primera, la estructura
de selección simple. La sintaxis que utiliza es "If",
la evaluación de una condición, entonces realizamos un conjunto de acciones.
Desde un punto de vista de diagrama
de flujo, veríamos que evaluamos la condición, si
es cierta realizamos el conjunto de acciones que
describamos, si no es cierta seguimos en secuencia.
Por ejemplo, si X es par y X es mayor o igual
que 8, realizaremos el conjunto de
acciones que podamos incluir en este bloque.
Estamos en este caso describiendo que haremos el conjunto de acciones cuando
X tenga el valor 8, 10, 12, etc.
La estructura de selección doble tiene la siguiente sintaxis,
"Si" condición, entonces realizamos la acción 1,
"si no" realizamos la acción 2.
Desde el punto de vista de diagrama de flujo veremos que analizamos la
condición; si es cierta incluimos el conjunto de acciones 1 a realizar;
si no es cierta, indicamos el conjunto de acciones 2 a realizar.
Por ejemplo, si X es par y X es mayor o igual
que 8 realizaremos las acciones 1, si
es el caso contrario realizaremos las acciones 2.
Por tanto, la diferencia entre este ejemplo
y el que hemos visto anteriormente, es
que en este segundo realizamos un conjunto
de acciones cuando la condición <b>no</b> se cumple.
En cambio en el primero solamente realizábamos
las acciones cuando se cumplía la condición.
Estructuras de selección múltiple.
La sintaxis es: "si" condición, entonces realizamos la acción 1;
"si no" "si" la condición dos es cierta realizamos
la acción 2, "si no" "si" la condición 3
es cierta realizamos la acción 3, y podríamos continuar sucesivamente.
Desde un punto de vista gráfico,
la realización de esta estructura múltiple sería:
evalúo la condición, si es cierta ya defino las acciones a
realizar, si no es cierta paso a evaluar una segunda condición.
Si es cierta ya evaluamos y hacemos las acciones, si no
es cierta pasamos a evaluar una tercera condición y así sucesivamente.
Por ejemplo, si A es igual a 1 realizamos en este caso
la asignación a la variable Z de la suma de las dos
variables X e Y. Si no, si A es igual a 2
lo que estamos realizando es la resta entre dos variables X e
Y sobre la variable Z; si no, si la variable vale 3
o cualquier valor superior a 3, lo que estamos realizando es la multiplicación.
Por lo tanto, hemos definido con esta estructura múltiple, tres
acciones distintas a realizar, la suma, la resta o la
multiplicación en función de tres condiciones distintas que hemos evaluado.
O bien cuando A vale 1, o bien cuando A vale 2
o bien cuando A vale 3 o un valor superior a 3.
Vamos a proponer un ejercicio en el que debemos calcular el pseudocódigo
de la operación X dividido entre 2 redondeando por defecto.
Para ello analizaremos los diferentes casos.
Cuando X es par, el resultado de la división siempre
será exacto tanto si X es positivo como si es negativo.
Por ejemplo, si X vale 8 el resultado será 8 ente 2, 4.
En cambio si X vale -8, el resultado
igualmente será realizar (-8) / 2 = -4.
Cuando X es impar, el redondeo lo deberemos calcular de manera diferente.
Si es negativo el cálculo a realizar será X más 1 dividido por 2.
Por ejemplo, si X vale -7 realizaremos (-7) + 1,
es decir, -6, (-6) / 2 = -3.
Si es positivo el cálculo será (X - 1) / 2.
Por ejemplo, si X igual a 7, Y valdrá (7-1) = 6; 6/2 = 3.
Vamos a resolver el ejercicio propuesto.
Queremos realizar en pseudocódigo la operación
X dividido entre dos redondeando por defecto.
Los diferentes casos analizados han sido: cuando X es par, el
resultado siempre será exacto tanto si es positivo como si es negativo.
En cambio cuando X era impar, el redondeo se calculaba de manera diferente,
en el caso negativo con esta fórmula y en el caso positivo con esta otra.
Por tanto, el pseudocódigo que implementa esta operación será
el siguiente: si condición, es decir si X es par,
entonces asignamos a la variable Y el valor X/2.
Si no, por tanto si X es impar, si X es negativo asignamos
a la variable Y el valor (X+1)/2; si no, es decir,
si X es positivo asignamos a la variable Y el
valor (X-1)/2. Estructuras de selección.
Vamos a ver las estructuras de selección. Case.
Con esta estructura el resultado de una
expresión nos permite escoger entre un conjunto
de bloques alternativos. Evaluamos la condición X, y si toma el
valor 1, realizaremos el conjunto de acciones 1, cuando toma el valor 2
las acciones 2, valor 3 acciones 3 y así sucesivamente.
Podemos ver el esquema en diagrama de bloques en el que
evaluamos la condición y en función de su valor nos derivaremos
hacia una de las posibles alternativas que hayamos establecido.
Por ejemplo, si X es un dígito decimal y queremos tener su representación
en binario sobre la variable Y, utilizaremos la estructura Case.
"Case" X valga 0, asignamos a la variable Y su representación
en binario, 0000. Cuando vale 1 le asignamos el
valor 0001.
Cuando la variable X toma el valor 9 le asignamos
a la variable Y el valor 1001.
Estructuras de iteración.
Estas estructuras nos permiten repetir acciones
condicionadas a la evaluación de una expresión.
La primera de ellas que veremos es la estructura "While".
Es un esquema
iterativo con la condición de finalización del bucle al principio.
El número de iteraciones es variable y el bloque de
acciones se repite mientras la evaluación de la condición sea cierta.
Por tanto, hacemos, "mientras condición cierta"
realizar el bucle involucrado en las acciones.
Estructura "For". En este esquema iterativo el número
de iteraciones es constante y está controlado por
un contador que se inicializa al valor mínimo.
Cada vez que se ejecuta el bucle se incrementa hasta llegar a un valor máximo.
Vamos a proponer el siguiente ejercicio: Dados dos vectores de 8 posiciones
a(0), a(1), hasta la posición a(7) y el
vector x(0), x(1) hasta la posición x(7), queremos realizar
el cálculo de a(0) por x(0), a(1) por x(1), sumándole
los siguientes valores hasta el valor a(7) por x(7).
Vamos a resolver el ejercicio propuesto.
Queríamos, dados dos vectores, resolver esta fórmula.
Para ello utilizamos la estructura "For". Inicializamos primero
una variable que le llamamos acumulador con el valor 0 y hacemos una
estructura repetitiva en la que el índice irá cambiando desde el valor 0
hasta el valor 7 y nos irá acumulando en la variable
"acc", acumulador, los diferentes cálculos.
La primera vez realizaremos el cálculo de "acumulador toma el valor 0
más a(0) por x(0)","
y así sucesivamente iremos incrementando la variable y hasta el valor máximo.
Vamos a comentar el último apartado correspondiente a esta lección.
Vamos a ver los procedimientos o subrutinas.
Un procedimiento
es un conjunto de acciones a realizar que resuelven una tarea concreta.
A cada procedimiento se le asigna un nombre con el
que puede ser llamado desde otra parte de nuestro programa principal.
Vemos en este esquema donde tenemos un algoritmo en
el que hemos definido una llamada a un procedimiento.
Se ejecutan el conjunto de instrucciones involucradas en
dicho procedimiento y al acabarse devuelve el control a
la instrucción siguiente desde donde se produjo la llamada.
Cuando llamamos a un procedimiento sólo debemos dar valor a las variables que
intervienen, los parámetros, y dichos valores se
asignarán cuando realicemos la llamada al mismo.
Los procedimientos nos facilitan el diseño, la estructura y la comprensión
de los algoritmos y nos evitan repetir sentencias en el algoritmo principal.
Vamos a explicar un ejemplo
de uso de los procedimientos.
Queremos realizar el cálculo de a.√x + b.√y por raíz cuadrada
Queremos realizar el cálculo de a.√x + b.√y por raíz cuadrada
En este ejemplo queremos hacer dos cálculos muy similares,
√x y √y,
por lo que parece adecuado definir un procedimiento que
vamos a denominar raíz_cuadrada y que tendrá tres parámetros.
El primero corresponde al valor sobre el cual
queremos realizar el cálculo.
El segundo parámetro corresponde a la variable
sobre la que vamos a devolver el resultado.
Y finalmente el parámetro n nos está definiendo
los dígitos fraccionarios con los que vamos a trabajar.
Por lo tanto la propuesta de nuestro algoritmo
será la siguiente: primero una llamada al procedimiento
raíz_cuadrada en este caso con el parámetro x
de entrada puesto que queremos realizar el primer cálculo.
Se devolverá el resultado sobre la variable u,
y vamos a trabajar con 16 dígitos fraccionarios.
Una vez el procedimiento ha realizado el cómputo se devuelve el resultado
sobre la variable u, por lo tanto podemos pasar a realizar el primer
producto del valor a por la variable u que contendrá el valor de
√x, guardándose este primer cálculo en la misma variable u.
Ahora podemos hacer de nuevo una llamada al procedimiento raíz_cuadrada,
en este caso con el parámetro de entrada y.
El resultado nos lo va a devolver sobre la
variable r, y de nuevo trabajamos con 16 dígitos fraccionarios.
Una vez ejecutado el procedimiento, la variable r contendrá el valor de
√y, por lo tanto podremos hacer este producto de b por r;
por tanto b por √y,
almacenándose de nuevo en la misma variable r.
Finalmente acabamos ya de calcular este valor seguido del
siguiente por lo que podemos proceder a la última suma.
Vamos a ver esta ejecución de un modo más gráfico.
En este algoritmo como hemos indicado se produce la
primera llamada al procedimiento con la variable x de entrada.
Ejecutamos el procedimiento para
que calcule el valor de la √x, y
este procedimiento nos va a devolver el resultado sobre la variable u.
Una vez tenemos el cálculo de √x en la variable u
podemos multiplicarla por el valor a y almacenarlo en la misma variable u.
De nuevo vamos a proceder ahora a la llamada del
procedimiento, en este caso con el valor de entrada y.
Ejecutamos de nuevo el procedimiento
y nos devuelve el resultado sobre la
variable r, trabajando también con 16 dígitos fraccionarios.
Una vez tenemos el valor en la variable r podemos multiplicarla por el
valor b para almacenar como hemos indicado el resultado en la variable r.
Finalmente sólo nos queda sumar la variable u más la
variable r almacenando el resultado final en la variable z.
Como resumen
de esta lección, hemos estado viendo la
representación de los algoritmos en formato pseudocódigo.
Concretamente hemos visto qué acciones y qué estructuras de control
son las más habituales, las asignaciones y operadores, estructuras de
control del tipo selección como son la simple, la doble
o múltiple y estructuras de control del tipo iteración, los While
y For.
Para acabar hemos estado viendo el concepto de procedimiento o
subrutina.