APUNTES DE LÓGICA DE PROGRAMACIÓN 1. LÓGICA DE … · Para llegar a la realización de un...
Transcript of APUNTES DE LÓGICA DE PROGRAMACIÓN 1. LÓGICA DE … · Para llegar a la realización de un...
1
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
APUNTES DE LÓGICA DE PROGRAMACIÓN
1. LÓGICA DE PROGRAMACIÓN
1.1 Introducción
La lógica de programación es la pieza fundamental en la que se basa la labor de una
persona que desea aprender a resolver problemas o situaciones con la ayuda de un
computador. Si bien la lógica es una capacidad inherente del ser humano, la lógica de
programación debe aprenderse y ejercitarse si se desea obtener resultados que permitan la
satisfacción de hacer algo que muy poca gente hace.
Aprender lógica de programación nos enseña a diseñar soluciones a problemas de la vida
real para su posterior implementación en forma de programas, sitios o aplicaciones que se
ejecutan en una gran variedad de dispositivos.
En el desarrollo de estos apuntes se trabajará paralelamente el desarrollo de la lógica para la
solución de problemas y el adiestramiento en el manejo de un lenguaje de programación, en
este caso C++, pero desarrollando los algoritmos en C#.
La principal razón para que las personas aprendan lógica de programación y lenguajes de
programación es utilizar el computador como una herramienta para resolver problemas. La
solución de problemas exige al menos los siguientes pasos:
1. Definición o análisis del problema.
2. Diseño del algoritmo.
3. Transformación del algoritmo en un programa.
4. Ejecución y validación del programa.
2
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
1.2 Conceptos y definiciones básicas
1.2.1 Algoritmo
Se denomina algoritmo a un grupo finito de operaciones organizadas de manera lógica
y ordenada que permite solucionar un determinado problema. Se trata de una serie de
instrucciones o reglas establecidas que, por medio de una sucesión de pasos, permiten
arribar a un resultado o solución.
Para llegar a la realización de un programa es necesario el diseño previo de un algoritmo, de
modo que sin algoritmo no puede existir un programa.
Los algoritmos son independientes tanto del lenguaje de programación en que se expresen
como del computador que los ejecute.
En la ciencia de la computación y en la programación, los algoritmos son más importantes
que los lenguajes de programación y que los computadores.
Dada la importancia de los algoritmos en la ciencia de la computación, un aspecto muy
importante será el diseño de algoritmos.
En esencia, la solución de un problema se puede expresar mediante un algoritmo.
1.2.1.1 Características de los algoritmos
Las características fundamentales que deben cumplir los algoritmos son:
Un algoritmo debe ser preciso e indicar el orden de realización de cada paso.
Un algoritmo debe estar definido. Si se sigue un algoritmo dos veces, se debe
obtener el mismo resultado cada vez.
Un algoritmo debe ser finito. Si se sigue un algoritmo, se debe terminar en algún
momento; o sea, debe tener un número finito de pasos.
La definición de un algoritmo debe describir tres partes: Entrada, Procesos y Salida.
1.2.2 Clasificación de los algoritmos
Los algoritmos se pueden clasificar en cuatro tipos:
3
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Algoritmo computacional: Es un algoritmo que puede ser ejecutado en una
computadora. Ejemplo: Fórmula aplicada para un cálculo de la raíz cuadrada de un
valor x.
Algoritmo no computacional: Es un algoritmo que no requiere de una computadora
para ser ejecutado. Ejemplo: Instalación de un equipo de sonido.
Algoritmo cualitativo: Un algoritmo es cualitativo cuando en sus pasos o
instrucciones no están involucrados cálculos numéricos. Ejemplos: Las instrucciones
para desarrollar una actividad física, encontrar un tesoro.
Algoritmo cuantitativo: Una algoritmo es cuantitativo cuando en sus pasos o
instrucciones involucran cálculos numéricos. Ejemplo: Solución de una ecuación de
segundo grado.
1.2.3 Representación de los algoritmos
Para la representación de un algoritmo, antes de ser convertido a lenguaje de programación,
se utilizan algunos métodos de representación escrita, gráfica o matemática. Los métodos
más conocidos son:
Diagramación libre (Diagramas de flujo).
Diagramas Nassi-Shneiderman.
Pseudocódigo.
Lenguaje natural (español, inglés, etc.).
Fórmulas matemáticas.
Ejercicios:
Realice los algoritmos para resolver las siguientes actividades:
1. Ir a cine.
2. Preparar una receta de cocina.
3. Hacer una llamada telefónica.
4. Cambiar una llanta de un carro.
5. Iniciar una conversación por WhatsApp
6. Bañarse.
Vea una selección de los mejores algoritmos: Pedro Javier Arguello, Ing. Civil III Semestre.
Laura Daniela Álvarez, Ing. Civil III Semestre. Danna Fuentes, Ing. Civil III Semestre.
4
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
1.3. Lenguaje de programación
Es un idioma artificial diseñado para expresar computaciones que pueden ser llevadas a
cabo por máquinas como los computadores. Pueden usarse para crear programas que
controlen el comportamiento físico y lógico de una máquina, para expresar algoritmos con
precisión, o como modo de comunicación humana.
Está formado de un conjunto de símbolos y reglas sintácticas y semánticas que definen su
estructura y el significado de sus elementos y expresiones. Al proceso por el cual se escribe,
se prueba, se depura, se compila y se mantiene el código fuente de un programa informático
se le llama programación.
También la palabra programación se define como el proceso de creación de un programa de
computador, mediante la aplicación de procedimientos lógicos, a través de los siguientes
pasos:
El desarrollo lógico del programa para resolver un problema en particular.
Escritura de la lógica del programa empleando un lenguaje de programación
específico (codificación del programa)
Ensamblaje o compilación del programa hasta convertirlo en lenguaje de máquina.
Prueba y depuración del programa.
Desarrollo de la documentación.
Los lenguajes de programación permiten especificar de manera precisa sobre qué datos
debe operar un computador, cómo deben ser almacenados o transmitidos y qué acciones
debe tomar bajo una variada gama de circunstancias. Todo esto, a través de un lenguaje que
intenta estar relativamente próximo al lenguaje humano o natural, tal como sucede con el
lenguaje léxico. Una característica relevante de los lenguajes de programación es
precisamente que más de un programador pueda usar un conjunto común de instrucciones
que sean comprendidas entre ellos para realizar la construcción del programa de forma
colaborativa.
5
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
1.3.1 Breve historia de los lenguajes de programación
Para que el computador entienda nuestras instrucciones debe usarse un lenguaje específico
conocido como código máquina, el cual la máquina comprende fácilmente, pero que lo hace
excesivamente complicado para las personas. De hecho sólo consiste en cadenas
interminables de números 1 y 0. (Binario)
Para facilitar el trabajo, los primeros operadores de computadoras decidieron reemplazar los
1 y 0 por palabras o letras provenientes del inglés; éste se conoce como lenguaje
ensamblador. Por ejemplo, para sumar se usa la letra A de la palabra inglesa add (sumar).
En realidad escribir en lenguaje ensamblador es básicamente igual que hacerlo en lenguaje
máquina, pero las letras y palabras son más fáciles de recordar y entender que los números.
La necesidad de recordar secuencias de programación para las acciones usuales llevó a
denominarlas con nombres fáciles de memorizar y asociar: ADD (sumar), SUB (restar), MUL
(multiplicar), CALL (ejecutar subrutina), etc. A esta secuencia de posiciones se le denominó
"instrucciones", y a este conjunto de instrucciones se le llamó lenguaje ensamblador.
Posteriormente aparecieron diferentes lenguajes de programación, los cuales reciben su
denominación porque tienen una estructura sintáctica similar a los lenguajes escritos por los
humanos, denominados también lenguajes de alto nivel.
La primera programadora de computadores conocida fue Ada Lovelace, hija de Anabella
Milbanke Byron y Lord Byron. Anabella introdujo en las matemáticas a Ada quien, después
de conocer a Charles Babbage, tradujo y amplió una descripción de su máquina analítica.
Incluso aunque Babbage nunca completó la construcción de cualquiera de sus máquinas, el
trabajo que Ada realizó con éstas le hizo ganarse el título de primera programadora de
computadores del mundo. El nombre del lenguaje de programación Ada fue escogido como
homenaje a esta programadora.
A finales de 1953, John W. Backus sometió una propuesta a sus superiores en IBM para
desarrollar una alternativa más práctica al lenguaje ensamblador para programar el
computador central IBM 704. El histórico equipo Fortran de Backus consistió en los
programadores Richard Goldberg, Sheldon F. Best, Harlan Herrick, Peter Sheridan, Roy
Nutt, Robert Nelson, Irving Ziller, Lois Haibt y David Sayre.
6
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
El primer manual para el lenguaje Fortran apareció en octubre de 1956, con el
primer compilador Fortran entregado en abril de 1957. Esto era un compilador optimizado,
porque los clientes eran reacios a usar un lenguaje de alto nivel a menos que su compilador
pudiera generar código cuyo desempeño fuera comparable al de un código hecho a mano en
lenguaje ensamblador.
En 1960, se creó COBOL, uno de los lenguajes usados aun en 2010 en informática de
gestión.
A medida que la complejidad de las tareas que realizaban los computadores aumentaba, se
hizo necesario disponer de un método más eficiente para programarlos. Entonces, se
crearon los lenguajes de alto nivel, como lo fue el BASIC en las versiones introducidas en los
microordenadores de la década de 1980. Mientras que una tarea tan sencilla como sumar
dos números puede necesitar varias instrucciones en lenguaje ensamblador, en un lenguaje
de alto nivel bastará con solo una.
1.3.2 Implementación de un lenguaje de programación
La implementación de un lenguaje es la que provee una manera de que se ejecute un
programa para una determinada combinación de software y hardware. Existen básicamente
dos maneras de implementar un lenguaje:
1.3.2.1 Compilación
Es la traducción a un código que pueda utilizar la máquina. Los programas traductores que
pueden realizar esta operación se llaman compiladores. Éstos, como los programas
ensambladores avanzados, pueden generar muchas líneas de código de máquina por cada
proposición del programa fuente.
1.3.2.2 Interpretación
Se puede también utilizar una alternativa para traducir lenguajes de alto nivel. En lugar de
traducir el programa fuente y grabar en forma permanente el código objeto que se produce
durante la compilación para utilizarlo en una ejecución futura, el programador sólo carga el
programa fuente en la computadora junto con los datos que se van a procesar. A
continuación, un programa intérprete, almacenado en el sistema operativo del disco, o
7
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
incluido de manera permanente dentro de la máquina, convierte cada proposición del
programa fuente en lenguaje de máquina conforme vaya siendo necesario durante el
procesamiento de los datos. El código objeto no se graba para utilizarlo posteriormente.
La mayoría de lenguajes de alto nivel, permiten la programación multipropósito, sin embargo,
muchos de ellos fueron diseñados para permitir programación dedicada, como lo fue
PASCAL con las matemáticas en su comienzo. También, se han implementado lenguajes
educativos infantiles como LOGO que mediante una serie de simples instrucciones, permitía
mover una tortuga entre otras cosas. En el ámbito de infraestructura de internet, cabe
destacar a Perl con un poderoso sistema de procesamiento de texto y una enorme colección
de módulos.
1.3.3 Clasificación de los lenguajes de programación
Los lenguajes de programación generalmente se dividen en dos grupos principales en base
al procesamiento de sus comandos:
1.3.3.1 Lenguajes imperativos
Un lenguaje imperativo programa mediante una serie de comandos, agrupados en bloques y
compuestos de órdenes condicionales que permiten al programa retornar a un bloque de
comandos si se cumple la condición. Estos fueron los primeros lenguajes de programación
en uso y aún hoy muchos lenguajes modernos usan este principio.
No obstante, los lenguajes imperativos estructurados carecen de flexibilidad debido a la
secuencialidad de las instrucciones.
1.3.3.2 Lenguajes funcionales
Un lenguaje de programación funcional (a menudo llamado lenguaje procedimental) es un
lenguaje que crea programas mediante funciones, devuelve un nuevo estado de resultado y
recibe como entrada el resultado de otras funciones. Cuando una función se invoca a sí
misma, hablamos de recursividad.
8
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
1.3.4 Lenguajes interpretados
Un lenguaje de programación es, por definición, diferente al lenguaje máquina. Por lo tanto,
debe traducirse para que el procesador pueda comprenderlo. Un programa escrito en un
lenguaje interpretado requiere de un programa auxiliar (el intérprete), que traduce los
comandos de los programas según sea necesario
1.3.5 Lenguajes compilados
Un programa escrito en un lenguaje "compilado" se traduce a través de un programa anexo
llamado compilador que, a su vez, crea un nuevo archivo independiente que no necesita
ningún otro programa para ejecutarse a sí mismo. Este archivo se llama ejecutable.
Un programa escrito en un lenguaje compilado posee la ventaja de no necesitar un programa
anexo para ser ejecutado una vez que ha sido compilado. Además, como sólo es necesaria
una traducción, la ejecución se vuelve más rápida. Sin embargo, no es tan flexible como un
programa escrito en lenguaje interpretado, ya que cada modificación del archivo fuente (el
archivo comprensible para los seres humanos: el archivo a compilar) requiere de la
compilación del programa para aplicar los cambios.
Por otra parte, un programa compilado tiene la ventaja de garantizar la seguridad del código
fuente. En efecto, el lenguaje interpretado, al ser directamente un lenguaje legible, hace que
cualquier persona pueda conocer los secretos de fabricación de un programa y, de ese
modo, copiar su código o incluso modificarlo. Por lo tanto, existe el riesgo de que los
derechos de autor no sean respetados. Por otro lado, ciertas aplicaciones aseguradas
necesitan confidencialidad de código para evitar las copias ilegales (transacciones bancarias,
pagos en línea, comunicaciones seguras...).
1.3.5.1 Fases de la compilación
La compilación es el proceso de traducción de programas fuentes a programas objeto. El
programa objeto obtenido de la compilación ha sido traducido normalmente a código
máquina.
9
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Para conseguir el programa máquina real se debe utilizar un programa llamado montador o
enlazador (linker). El proceso de montaje conduce a un programa en lenguaje máquina
directamente ejecutable.
Programa fuente
Compilador
(Traductor)
Programa objeto
Montador
Programa ejecutable en
lenguaje máquina
Fases de la compilación
1.3.6 lenguajes intermediarios
Algunos lenguajes pertenecen a ambas categorías (LISP, Java, Python...) dado que el
programa escrito en estos lenguajes puede, en ciertos casos, sufrir una fase de compilación
intermediaria, en un archivo escrito en un lenguaje ininteligible (por lo tanto, diferente al
archivo fuente) y no ejecutable (requeriría un intérprete). Los applets Java, pequeños
programas que a menudo se cargan en páginas web, son archivos compilados que sólo
pueden ejecutarse dentro de un navegador web (son archivos con la extensión .class).
Vea aquí un resumen de este tema con los mejores mapas conceptuales realizados con
Cmaptools por los estudiantes:
Leonardo Becerra, Didier Florez, Estudiantes de Ing. Civil III Semestre
10
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
1.4 Datos, Tipos de datos y operaciones primitivas
1.4.1 Dato
Es la expresión general que describe los objetos con los cuales opera un computador.
La acción de las instrucciones ejecutables de los computadores se refleja en cambios en los
valores de las partidas de datos. Los datos de entrada se transforman por el programa,
después de las etapas intermedias, en datos de salida.
Existen dos clases de tipos de datos: simples (sin estructura) y compuestos (estructurados)
Los distintos tipos de datos se representan en diferentes formas en el computador. A nivel
de máquina un dato es un conjunto o secuencias de bits (dígitos 0 o 1). Los lenguajes de
alto nivel permiten basarse en abstracciones e ignorar los detalles de la representación
interna.
1.4.1.1 Tipos de datos simples
1.4.1.1.1 numérico: es el conjunto de los valores numéricos. Estos pueden representarse en
dos formas distintas:
Tipo numérico entero (integer, int), subconjunto finito de los números enteros,
completos, no tienen componentes fraccionarios o decimales, pueden ser positivos o
negativos. En algunos lenguajes de programación están en el rango -32768 a 32767
Tipo numérico real (real), subconjunto de los números reales, tienen un punto decimal
y pueden ser positivos o negativos.
1.4.1.1.2 lógicos (booleanos): es aquel que solo puede tomar uno de dos valores:
Cierto o verdadero (true) y falso (false).
1.4.1.1.3 carácter y cadena:
Carácter: conjunto finito y ordenado de caracteres que el computador reconoce. Un dato
carácter contiene un solo carácter.
Pueden ser:
11
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Caracteres alfabéticos (A, B, C,…, Z), (a, b, c,…, z)
Caracteres numéricos (1, 2, . . ., 9, 0)
Caracteres especiales (+ - * / ^ , ; : <, >, %, $, #,…)
Cadena: (string) de caracteres: es una sucesión de caracteres que se encuentran
delimitados por una comilla (apóstrofo) o dobles comillas, según el tipo de lenguaje de
programación
1.5 Constantes y Variables
1.5.1 Constantes
Es una partida de datos (objetos) que permanecen sin cambios durante todo el desarrollo del
algoritmo o durante la ejecución del programa.
Las constantes pueden ser números, carácter, cadena de caracteres, lógica o booleana
1.5.2 Variables
Una variable es un objeto o partida de datos cuyo valor puede cambiar durante el desarrollo
del algoritmo o ejecución del programa.
Una variable que es de un cierto tipo sólo puede tomar valores de ese tipo, si se intenta
asignar un valor de otro tipo se produce un error de tipo.
Una variable se identifica por los siguientes atributos: nombre que lo asigna y tipo que
describe el uso de la variable.
Los nombres de las variables elegidas para el algoritmo o el programa deben ser
significativos y tener relación con el objeto que representan, por ejemplo, si se quiere guardar
el nombre de una persona, la variable debería llamarse nombre o name, si se va a guardar el
precio de algún objeto, la variable debería llamarse precio o costo.
1.6 Expresiones
Las expresiones son combinaciones de constantes, variables, símbolos de operaciones,
paréntesis y nombres de funciones especiales. Por ejemplo
12
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
x + a(b + 5) + ln(10)
Las expresiones pueden ser aritméticas, lógicas o carácter.
1.6.1 Expresiones aritméticas
Son análogas a las fórmulas matemáticas y las operaciones son las aritméticas.
+ Suma - Resta * Multiplicación / División ^ Potencia div División entera
mod Módulo (residuo).
1.6.1.1 Reglas de prioridad
Las expresiones que tienen dos o más operandos requieren unas reglas matemáticas que
permitan determinar el orden de las operaciones, se denominan reglas de prioridad o
precedencia y son:
1. Las operaciones que están encerradas entre paréntesis se evalúan primero, si existen
diferentes paréntesis anidados (interiores unos a otros), las expresiones más internas
se evalúan primero.
2. Las operaciones aritméticas dentro de una expresión suelen seguir el siguiente orden
de prioridad:
Operador exponencial
Operadores *, /,\
Operadores div y mod
Operadores +, -
En caso de coincidir varios operadores de igual prioridad en una expresión o subexpresión
encerrada entre paréntesis, el orden de prioridad en este caso es de izquierda a derecha.
1.6.2 Expresiones lógicas (booleanas)
Son aquellas que solo pueden tomar un valor de dos posibles: verdadero (true) o falso
(false).
13
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
1.6.2.1 Operadores de relación
Los operadores relacionales o de relación permiten realizar comparaciones de valores de tipo
numérico o carácter. Los operadores relacionales sirven para expresar las condiciones en los
algoritmos, el formato general para su uso es:
Expresión1 operador de relación expresión 2
Los operadores de relación son:
< Menor que > mayor que = igual que <= menor o igual
que >= mayor o igual que < > diferente de
1.6.2.2 Operadores lógicos
Los operadores lógicos o booleanos básicos son not (no), and (y) y or (o)
Las definiciones de las operaciones de los operadores lógicos se resumen en las siguientes
tablas.
a no a
v f
f v
1.7 La operación de asignación
a b a and b
v v v
v f f
f v f
f f f
a b a or b
v v v
v f v
f v v
f f f
14
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
La operación de asignación es el modo de darle valores a una variable. Esta operación se
representa con al símbolo u operador. También se conoce como instrucción o sentencia
de asignación cuando se refiere a un lenguaje de programación.
El formato general de esta operación es:
Nombre de la variable expresión
En algunos lenguajes de programación la operación de asignación se remplaza por =
(BASIC, FORTRAN, COBOL), por := (C, C++, PASCAL).
La instrucción A 5 significa que a la variable A se le ha asignado el valor entero 5.
Una característica fundamental de la operación de asignación es que esta es destructiva,
es decir, elimina el penúltimo valor que se le haya asignado, dejando solo el último.
El computador ejecuta la operación de asignación en dos pasos: Primero se calcula el valor
de la expresión al lado derecho del operador, obteniéndose un valor de un tipo de dato
específico.
Segundo, este valor se almacena en la variable cuyo nombre aparece al lado izquierdo del
operador.
Por ejemplo, en las sentencias de asignación
N 1
NN+1
En la primera sentencia, a la variable N se le asigna el valor de 1.
En la segunda sentencia, primero se realiza la operación N + 1, como N tiene el valor de 1 se
suma 1, quedando la operación en 2, luego este valor es asignado a la variable N, que
elimina el valor anterior (1) y conserva el valor final 2.
1.7.1 Asignación aritmética
Las expresiones en la operación de asignación son aritméticas:
IVA 0.16
15
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
PRECIO 50000
TOTAL_FACTURA PRECIO*IVA + PRECIO
1.7.2 Asignación lógica
La expresión que se evalúa en la operación de asignación es lógica, por ejemplo.
M 8<10
Se hace la comparación lógica 8 < 10, y este valor (true) se guarda en la variable M.
1.7.3 Asignación de cadena de caracteres
La expresión que se evalúa es de tipo cadena:
FECHA ’01/08/2016’
1.7.4 Conversión de tipo
En las asignaciones no se puede asignar valores a una variable de un tipo diferente del suyo.
Se presentará un error de tipo.
1.8 Entrada y salida de información
Las operaciones de entrada permiten leer determinados valores y asignarlos a determinadas
variables. Esta entrada se conoce como operación de lectura (read).
La salida puede aparecer en un dispositivo de salida. La operación de salida se denomina
escritura (write).
En la escritura de algoritmos las acciones de lectura y escritura se representan por los
formatos:
leer (lista de variables de entrada)
escribir (Lista de expresiones de salida)
16
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Taller No. 1
Solución:
Solución:
Solución:
Solución:
17
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Solución
Solución
Solución
18
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Solución
Solución
Solución
19
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Solución
Solución
Solución
20
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
2. RESOLUCIÓN DE PROBLEMAS CON COMPUTADOR Y HERRAMIENTAS DE
PROGRAMACION.
2.1 La resolución de problemas
El principal objetivo de aprender a programar o aprender un lenguaje de programación es
utilizar el computador como una herramienta que permita hacer más rápido el procedimiento
de solución y realizar los cálculos repetitivos en forma automática.
La resolución de un problema se puede dividir en tres fases o etapas importantes:
1. Análisis del problema
2. Diseño o desarrollo del algoritmo.
3. Resolución del algoritmo en el computador
El primer paso – análisis del problema – requiere que el problema sea definido y
comprendido claramente para que pueda ser analizado con todo detalle. Una vez analizado
el problema se debe desarrollar el algoritmo – procedimiento paso a paso para solucionar
el problema dado – Por último, para resolver el algoritmo mediante un computador se
necesita codificar el algoritmo en un lenguaje de programación Pascal, C, C++, COBOL,
ADA, FORTRAN, JAVA, entre otros.
Resolución de un problema
2.1.1 Análisis del problema
Resolución de un
problema
Análisis del problema Diseño del algoritmo Resolución del
problema con el
computador
21
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
El principal propósito del análisis de un problema es ayudar al programador a entender la
naturaleza del problema. El problema debe estar bien definido si se desea llegar a una
solución satisfactoria.
Para definir bien un problema se requiere que las especificaciones de entrada y salida sean
descritas con detalle.
El análisis del problema exige una lectura previa del problema a fin de obtener una idea
general de lo que solicita. Una segunda lectura deberá servir para responder las siguientes
preguntas:
¿Qué información debe proporcionar la resolución del problema?
¿Qué datos se necesitan para resolver el problema?
La respuesta a la primera pregunta indicará los resultados deseados o las salidas del
problema.
La segunda respuesta indicará que datos se proporcionan o las entradas del problema.
Análisis del problema
Ejemplo:
Leer el radio de una esfera y calcular el área superficial y el volumen.
Análisis
Para la resolución de este problema se necesita conocer como entrada el valor del radio de
la esfera y además las fórmulas matemáticas necesarias para calcular el área superficial y el
volumen de la esfera.
Las salidas serán las variables área, volumen.
2.1.2 Diseño del algoritmo
Análisis del problema
Definición del
problema
Especificaciones de
entrada
Especificaciones de
salida
22
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
El computador no tiene la capacidad de solucionar problemas, por lo tanto, se le deben
proporcionar los pasos sucesivos, lógicos, bien definidos y finitos – algoritmo – para tal fin.
Muchas veces los problemas de mayor complejidad se descomponen en subproblemas un
poco más simples y estos a su vez en otros subproblemas, a esta técnica se le conoce como
diseño descendente (top down design).
Normalmente los pasos diseñados en el primer esbozo del algoritmo son incompletos e
indicarán solo unos pocos pasos. Luego de esta primera descripción, estos se amplían en
una descripción más detallada con más pasos específicos, a este proceso se le denomina
refinamiento del algoritmo (stepwise refinement).
Las ventajas más importantes del diseño descendente son:
El problema se comprende más fácilmente al dividirse en partes más simples
denominados módulos.
Las modificaciones en los módulos son más fáciles.
La comprobación del problema se puede verificar fácilmente.
Fases del diseño de un algoritmo
2.1.2.1 Escritura inicial del algoritmo
Diseño de un
algoritmo
Diseño descendente Refinamiento por
pasos
Herramientas de
programación
- Diagrama de flujo
- Pseudocódigo
23
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
El sistema para escribir un algoritmo consiste en hacer una descripción paso a paso con un
lenguaje natural del citado algoritmo. El conjunto de reglas para solucionar un problema –
algoritmo - tiene las siguientes propiedades:
Deben estar seguidas de alguna secuencia definida de pasos hasta que se obtenga un
resultado coherente.
Sólo puede ejecutarse una operación a la vez.
2.2 Resolución de problemas mediante un computador
Una vez el diseño del algoritmo este completo y representado gráficamente mediante una
herramienta de programación (diagrama de flujo, pseudocódigo o diagrama N-S) se debe
pasar a la fase de resolución práctica del problema con un computador. Esta fase se
descompone en tres subfaces:
1. Codificación del algoritmo en un programa.
2. Ejecución del programa.
3. Comprobación del programa.
Resolución de un problema mediante computador
Resolución del
problema con
computador
Codificación del
programa
Ejecución del
programa
Comprobación del
programa
24
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
2.3 Representación de los algoritmos
Los métodos más usuales para la representación de algoritmos son:
Diagrama de flujo.
Diagrama N-S (Nassi-Schneiderman).
Pseudocódigo. 2.3.1 Diagramas de flujo
Los diagramas de flujo se utilizan tanto para la representación gráfica de las operaciones
ejecutadas sobre los datos a través de todas las partes de un sistema de procesamiento de
información, diagrama de flujo del sistema, como para la representación de la secuencia de
pasos necesarios para describir un procedimiento particular, diagrama de flujo de detalle. En
la actualidad se siguen usando los diagramas de flujo del sistema, pero ha decaído el uso de
los diagramas de flujo de detalle al aparecer otros métodos de diseño estructurado más
eficaces para la representación y actualización de los algoritmos.
Los diagramas de flujo de detalle son, no obstante, uno de nuestros objetivos prioritarios y, a
partir de ahora, los denominaremos simplemente diagramas de flujo.
El diagrama de flujo utiliza unos símbolos normalizados, con los pasos del algoritmo escritos
en el símbolo adecuado y los símbolos unidos por flechas, denominadas líneas de flujo, que
indican el orden en que los pasos deben ser ejecutados. Los símbolos principales son
25
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Ejemplo: Realice el diagrama de flujo de un algoritmo que convierta una cantidad de dólares
americanos a pesos colombianos y que muestre la conversión.
Solución:
Datos de entrada: Cantidad de dólares (Variable Cant_Dol)
Valor del dólar a la fecha (Variable Val_Dol)
Datos de salida: Cantidad en pesos colombianos (Variable Cant_Pes)
2.3.2 Diagramas de Nassi – Schneiderman (N-S)
También conocido como diagrama de Chapin – es como un diagrama de flujo donde se han
omitido las flechas de unión y los rectángulos de acciones van contiguos
Inicio
Can_Dol, Val_Dol
Can_Pes Can_Dol*Val_Dol
Can_Pes
Fin
26
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Veamos el mismo algoritmo en el diagrama de Nessi-Schneiderman
Cambiar
Inicio
Leer
Can_Dol, Val_Dol
Calcular
Can_Pes Can_Dol*Val_Dol
Escribir
Can_Pes
Fin
2.3.3 Pseudocódigo
El pseudocódigo es un lenguaje de especificación de algoritmos que utiliza palabras
reservadas y exige la indentación, o sea sangría en el margen izquierdo de algunas líneas. El
pseudocódigo se concibió para superar las dos principales desventajas del diagrama de flujo:
lento de crear y difícil de modificar sin un nuevo redibujo. Es una herramienta muy buena
para el seguimiento de la lógica de un algoritmo y para transformar con facilidad los
algoritmos a programas, escritos en un lenguaje de programación específico. En este libro se
escribirán casi todos los algoritmos en pseudocódigo.
En nuestro pseudocódigo utilizaremos palabras reservadas en español. Así, nuestros
algoritmos comenzarán con la palabra reservada inicio y terminarán con fin, constando de
múltiples líneas que se sangran o indentan para mejorar la legibilidad.
La estructura básica de un algoritmo escrito en pseudocódigo es:
algoritmo <identificador_algoritmo>
// declaraciones, sentencias no ejecutables
inicio
// acciones, sentencias ejecutables tanto simples como estructuradas
fin
Los elementos léxicos de nuestro pseudocódigo son: Comentarios, Palabras reservadas,
Identificadores, Operadores y signos de puntuación y Literales.
27
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
2.3.3.1 Comentarios
Los comentarios sirven para documentar el algoritmo y en ellos se escriben anotaciones
generalmente sobre su funcionamiento. Cuando se coloque un comentario de una sola línea
se escribirá precedido de //. Si el comentario es multilínea, lo pondremos entre {}.
// Comentario de una línea
{ Comentario que ocupa más
de una línea }
2.3.3.2 Palabras reservadas
Las palabras reservadas o palabras clave (Keywords) son palabras que tienen un
significado especial, como: inicio y fin, que marcan el principio y fin del algoritmo, y las
palabras que aparecen en negrita en las estructuras especificadas a continuación. En lugar
de las palabras reservadas no deberán utilizarse otras similares, aunque no se distingue
entre mayúsculas y minúsculas.
Decisión simple: si <condición> entonces
<acciones1>
fin_si
Decisión doble: si <condición> entonces
<acciones1>
si_no
<acciones2>
fin_si
Decisión múltiple: según_sea <expresión_ordinal> hacer
<lista_de_valores_ordinales>: <acciones1>
.......
[si_no // El corchete indica opcionalidad
<accionesN>]
fin_según
Repetitivas: mientras <condición> hacer
<acciones>
fin_mientras
repetir
<acciones>
hasta_que <condición>
28
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
desde <variable> <v_inicial> hasta <v_final>
[incremento | decremento <incremento>] hacer
<acciones>
fin_desde
2.3.3.3 Identificadores
Identificadores son los nombres que se dan a las constantes simbólicas, variables,
funciones, procedimientos, u otros objetos que manipula el algoritmo. La regla para construir
un identificador establece que:
Debe resultar significativo, sugiriendo lo que representa.
No podrá coincidir con palabras reservadas, propias del lenguaje algorítmico. Como se
verá más adelante, la representación de algoritmos mediante pseudocódigo va a
requerir la utilización de palabras reservadas.
Se recomienda un máximo de 50 caracteres.
Comenzará siempre por un carácter alfabético y los siguientes podrán ser letras,
dígitos o el símbolo de subrayado.
Podrá ser utilizado indistintamente escrito en mayúsculas o en minúsculas.
2.3.3.4 Operadores y signos de puntuación
Los operadores se utilizan en las expresiones e indican las operaciones a efectuar con los
operandos, mientras que los signos de puntuación se emplean con el objetivo de agrupar o
separar, por ejemplo. ; o [ ].
2.3.3.5 Literales
Los literales son los valores que aparecen directamente escritos en el programa y pueden
ser literales: lógicos, enteros, reales, de tipo carácter, de tipo cadena y el literal nulo.
Ejemplo del pseudocódigo del algoritmo anterior.
29
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Inicio
// Conversión de divisas
Variables
Can_Dol, Val_Dol, Can_Pes: Tipo Real
Lea
Can_Dol, Val_Dol
Haga
Calcule
Can_Pes Can_Dol*Val_Dol;
Muestre
Imprima
Can_Pes
Fin
30
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Taller No. 2
Realice el diagrama de flujo, psudocódigo, prueba de escritorio y código fuente en C++ de los
algoritmos que resuelvan las siguientes situaciones:
1. Resolver una ecuación de segundo grado de la forma ax2 + bx + c = 0, si las
soluciones son reales
2. Sumar los 10 primeros números enteros
3. Sumar independientemente los numero pares y los impares entre 1 y 100
4. Mostrar el mayor de dos números
5. Calcular el promedio de 10 números enteros cualquiera.
Código fuente
31
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Solución Taller 2
1. Resolver una ecuación de segundo grado de la forma ax2 + bx + c = 0, si las
soluciones son reales
Análisis del problema:
Para solucionar una ecuación de segundo grado de la forma ax2 + bx + c = 0, se utilizará la
fórmula cuadrática
Para esto, los valores que se deben introducir por teclado son los coeficientes a, b y c.
Para saber si una ecuación de este tipo tiene soluciones reales, se analiza el
discriminante
Si este discriminante es mayor o igual que cero, la ecuación tiene raíces reales, de lo
contrario las raíces son imaginarias.
Diagrama de flujo
no si
Inicio
a, b, c
Discb*b – 4*a*c
Disc >=0
Las raíces son
imaginarias
x1, x2
fin
32
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Diagrama de Nessi – Schneiderman
Ecuación de Segundo Grado
Inicio
Leer
a, b, c
Calcular
Disc b*b – 4*a*c
Disc>=0
Si
Calcule
Imprima
x1, x2
Imprima
Las raíces de esta
ecuación son
imaginarias
Fin
Pseudocódigo
/* Solución de una ecuación de segundo grado */
Inicio
Var a, b, c, disc, x1, x2: Real
Lea
a, b, c
Si Disc > = 0, entonces
;
;
Imprima
x1, x2
Si_no
Imprima
“Las raíces de la ecuación son imaginarias”
Fin si
Fin
si no
33
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Prueba de escritorio
Resolver:
3x2 + 5x – 6 = 0
3x2 + 5x + 6 = 0
a b c Disc x1 x2 Imprime
3 5 -6 97 0.08081429 -2.474809 0.08081429, -2.474809
3 5 6 -47 ------- -------- Las soluciones de la ecuación son imaginarias
Código fuente
#include <cstdlib>
#include <iostream>
#include <math.h>
using namespace std;
int main() {
float a,b,c,disc,x1,x2;
cout<<"SOLUCIÓN DE UNA ECUACION DE SEGUNDO GRADO"<<endl;
cout<<"Digite los valores de los coeficientes "<<endl;
cout<<"a :"; cin>>a; cout<<"b :"; cin>>b; cout<<"c :"; cin>>c;
disc = b*b-4*a*c;
if (disc >=0) {
x1 = (-b+sqrt(disc))/(2*a);
x2 = (-b-sqrt(disc))/(2*a);
cout<<"x1 = "<<x1<<endl;
cout<<"x2 = "<<x2<<endl;
}
else
cout<<"Las raices son imaginarias"<<endl;
return 0;
}
34
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
2. Sumar independientemente los números pares y los impares entre 1 y 100
Análisis del problema
Para sumar independientemente los números pares e impares utilizaremos dos variables
acumuladoras, es decir, que acumulan los valores que va guardando. Se inician en 0, en
una guardamos la suma de números pares y en la otra la suma de los impares. Además se
utilizará una variable entera que controle un ciclo o bucle repetitivo, en este caso que tome
los valores entre 1 y 100. A cada iteración de esta variable le aplicamos el operador mod,
con el cual sabremos si el número es par o impar.
Diagrama de flujo
Inicio
sumapar 0; sumaimp 0
Para i = 1 hasta 100
Des i mod 2
Des ==0
sumapar sumapar + i sumaimp sumaimp +
i
sumapar
sumaimp
Fin
35
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Pseudocódigo
/* Suma de números pares e impares */
Inicio
Var i: Entero, Des
sumapar, sumaimp: Real;
sumapar 0; sumaimp 0;
Para i = 1 hasta 100 haga
Des i mod 2;
Si (Des == 0) entonces
sumapar sumapar + i;
Si no
sumaimp sumaimp + i;
Fin si
Fin para
Imprima
sumapar, sumaimp
Fin
Código fuente
#include <cstdlib> #include <iostream> using namespace std; int main() { int i; float sumapar, sumaimp; sumapar = 0; sumaimp = 0; for(i=1;i<=100; i=i+1){ if (i%2==0) sumapar = sumapar + i; else sumaimp = sumaimp + i; } cout<<"La suma de los números pares es :"<<sumapar<<endl; cout<<"La suma de los números impares es :"<<sumaimp<<endl; return 0; }
36
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
3. INTRODUCCION A LA PROGRAMACIÓN ESTRUCTURADA
3.1 PROGRAMACIÓN ESTRUCTURADA
La programación estructurada es un conjunto de técnicas para desarrollar algoritmos
fáciles de escribir, verificar, leer y modificar.
La programación estructurada utiliza:
Diseño descendente. Consiste en diseñar los algoritmos en etapas, yendo de los
conceptos generales a los de detalle. El diseño descendente se verá completado y
ampliado con el modular.
Recursos abstractos. En cada descomposición de una acción compleja se supone
que todas las partes resultantes están ya resueltas, posponiendo su realización para
el siguiente refinamiento.
Estructuras básicas. Los algoritmos deberán ser escritos utilizando únicamente tres
tipos de estructuras básicas.
3.2 TEOREMA DE BÖHM Y JACOPINI
Para que la programación sea estructurada, los programas han de ser propios. Un programa
se define como propio si cumple las siguientes características:
Tiene un solo punto de entrada y uno de salida.
Toda acción del algoritmo es accesible, es decir, existe al menos un camino que va
desde el inicio hasta el fin del algoritmo, se puede seguir y pasa a través de dicha
acción.
No posee lazos o bucles infinitos
El teorema de Böhm y Jacopini dice que: “un programa propio puede ser escrito
utilizando únicamente tres tipos de estructuras: secuencial, selectiva y repetitiva”.
De este teorema se deduce que se han de diseñar los algoritmos empleando exclusivamente
dichas estructuras, la cuales, como tienen un único punto de entrada y un único punto de
salida, harán que nuestros programas sean propios.
37
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
3.3 CONTROL DEL FLUJO DE UN PROGRAMA
El flujo (orden en que se ejecutan las sentencias de un programa) es secuencial si no se
especifica otra cosa. Este tipo de flujo significa que las sentencias se ejecutan en secuencia,
una después de otra, en el orden en que se sitúan dentro del programa. Para cambiar esta
situación se utilizan las estructuras de selección, repetición y salto que permiten modificar
el flujo secuencial del programa. Así, las estructuras de selección se utilizan para
seleccionar las sentencias que se han de ejecutar a continuación y las estructuras de
repetición (repetitivas o iterativas) se utilizan para repetir un conjunto de sentencias.
Las sentencias de selección son: si («if») y según-sea («switch»); las sentencias de
repetición o iterativas son: desde («for»), mientras («while»), hacer-mientras («do-
while») o repetir-hasta que («repeat-until»); las sentencias de salto incluyen interrumpir
(break), continuar (continue), ir-a (goto), volver (return) y lanzar (trhow).
3.3.1 Estructura secuencial
Una estructura secuencial es aquella en la cual una acción se ejecuta detrás de otra. El
flujo del programa coincide con el orden físico en el que se sitúan las instrucciones.
3.3.2 Estructura selectiva
Una estructura selectiva es aquella en que se ejecutan unas acciones u otras según se
cumpla o no una determinada condición.
La selección puede ser simple, doble o múltiple.
38
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Simple
Se evalúa la condición y si ésta da como resultado verdad se ejecuta una determinada
acción o grupo de acciones; en caso contrario se saltan dicho grupo de acciones.
Doble
Cuando el resultado de evaluar la condición es verdad se ejecutará una determinada acción
o grupo de acciones y si el resultado es falso otra acción o grupo de acciones diferentes.
Múltiple
Se ejecutarán unas acciones u otras según el resultado que se obtenga al evaluar una
expresión. Aunque la flexibilidad de esta estructura está muy condicionada por el lenguaje,
en nuestro pseudocódigo se considera que dicho resultado ha de ser de un tipo ordinal, es
decir de un tipo de datos en el que cada uno de los elementos que constituyen el tipo,
excepto el primero y el último, tiene un único predecesor y un único sucesor.
39
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Cada grupo de acciones se encontrará ligado con: un valor, varios valores separados por
comas, un rango, expresado como valor_inicial...valor_final o una mezcla de valores y
rangos.
Se ejecutarán únicamente las acciones del primer grupo que, entre los valores a los que está
ligado (su lista de valores), cuente con el obtenido al evaluar la expresión. Cuando el valor
obtenido al evaluar la expresión no está presente en ninguna lista de valores se ejecutarán
las acciones establecidas en la cláusula si_no, si existe dicha cláusula.
3.3.3 Estructura repetitiva
Las acciones del cuerpo del bucle se repiten mientras o hasta que se cumpla una
determinada condición. Es frecuente el uso de contadores o banderas para controlar un
bucle. También se utilizan con esta finalidad los centinelas.
Un centinela es un valor específico predefinido dado a una variable que permite detectar
cuándo se desea terminar de repetir las acciones que constituyen el cuerpo del bucle. Por
ejemplo, se puede diseñar un bucle que pida el nombre y la nota de una serie de alumnos y
40
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
establecer que termine cuando se le introduzca un «*» como nombre. Podemos considerar
tres tipos básicos de estructuras repetitivas: mientras, hacer-mientras, hasta, desde.
Mientras
Lo que caracteriza este tipo de estructura es que las acciones del cuerpo del bucle se
realizan cuando la condición es cierta. Además, se pregunta por la condición al principio, de
donde se deduce que dichas acciones se podrán ejecutar de 0 a n veces.
Hacer mientras
El bucle hacer-mientras es análogo al bucle mientras desde el punto de vista de que el
cuerpo del bucle se ejecuta una y otra vez mientras la condición (expresión booleana) es
verdadera. La diferencia entre ellos consiste en que en el bucle hacer-mientras las
sentencias del cuerpo se ejecutan, al menos una vez, antes de que se evalúe la expresión
booleana. En otras palabras, el cuerpo del bucle siempre se ejecuta, al menos una vez,
incluso aunque la expresión booleana sea falsa. Este tipo de bucle es típico de C/C++, Java
o C#, pero no está presente en todos los lenguajes de programación por lo que será poco
usado en nuestros algoritmos.
41
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
hacer
<cuerpo_del_bucle>
mientras (<expresión_lógica>)
Hasta Las acciones del interior del bucle se ejecutan una vez y continúan repitiéndose mientras que
la condición sea falsa. Se interroga por la condición al final del bucle.
Desde
Se utiliza cuando se conoce, con anterioridad a que empiece a ejecutarse el bucle, el número
de veces que se va a iterar. La estructura desde comienza con un valor inicial de la variable
índice y las acciones especificadas se ejecutan a menos que el valor inicial sea mayor que el
valor final. La variable índice se incrementa en 1, o en el valor que especifiquemos, y si este
nuevo valor no excede al final se ejecutan de nuevo las acciones.
Si establecemos que la variable índice se decremente en cada iteración el valor inicial deberá
ser superior al final. Consideramos siempre la variable índice de tipo entero.
Es posible sustituir una estructura desde por otra de tipo mientras controlada por un
contador.
42
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
3.3.4 Estructura anidada
Tanto las estructuras selectivas como las repetitivas pueden ser anidadas, e introducidas
unas en el interior de otras.
La estructura selectiva múltiple es un caso especial de varias estructuras selectivas dobles
anidadas en la rama si_no.
si <condición1> entonces
<acciones1>
si_no
si <condición2> entonces
<acciones2>
si_no
si <condición3> entonces
<acciones3>
si_no
<accionesX>
fin_si
fin_si
fin_si
Cuando se inserta un bucle dentro de otro la estructura interna ha de estar totalmente
incluida dentro de la externa. Es posible anidar cualquier tipo de estructura repetitiva. Si se
43
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
anidan dos estructuras desde, para cada valor de la variable índice del ciclo externo se debe
ejecutar totalmente el bucle interno.
desde v1 vi1 hasta vf1 hacer
desde v2 vi2 hasta vf2 hacer
<acciones>
fin_desde
fin_desde
Las acciones que componen el cuerpo del bucle más interno se ejecutarán el siguiente
número de veces:
(vf1 - vi1 + 1) * (vf2 - vi2 + 1)
3.3.5 Sentencias de salto
Las sentencias de salto hacen que el flujo de control salte a otra parte del programa. Las
sentencias de salto o bifurcación que se encuentran en los lenguajes de programación, tanto
tradicionales como nuevos (Pascal, C, C++, C#, Java, etc.) son: ir-a (goto), interrumpir
(break), continuar (continue), devolver (return) y lanzar (trhow). Las cuatro primeras se
suelen utilizar con sentencias de control y como retorno de ejecución de funciones o
métodos. La sentencia throw se suele utilizar en los lenguajes de programación que poseen
mecanismos de manipulación de excepciones, como suelen ser los casos de los lenguajes
orientados a objetos tales como C++, Java y C#.
Con respecto a interrumpir (break), uno de sus usos es interrumpir un bucle en un lugar
determinado del cuerpo del mismo, en vez de esperar que termine de modo natural. A
diferencia de la sentencia continuar (continue) que hace que el flujo de ejecución salte el
resto de un cuerpo del bucle para continuar con la siguiente iteración, pero no interrumpe el
bucle. Por su parte, la sentencia ir-a (goto) transfiere la ejecución del programa a una
posición especificada por el programador. Las sentencias de salto interrumpir (break) e ir-a
(goto) y continuar (continue) deben ser evitadas habitualmente. No obstante, algún
lenguaje obliga a utilizar break y goto en sentencias switch (segun_sea). Así, en C# las
acciones asociadas a un determinado valor de la expresión selectora deben terminar con una
de estas instrucciones de salto, que habitualmente será break, o se producirá error. La
sentencia break hace que switch se abandone tras la ejecución de las acciones asociadas a
44
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
un determinado valor (situación por defecto en nuestro psudocódigo en las sentencias
segun_sea sin necesidad de especificar interrumpir). La instrucción goto se utiliza en
switch con la finalidad de transferir el control a otro punto, de forma que, después de
ejecutadas las acciones asociadas a un valor, se ejecuten las asociadas a otro o las
especificadas en la cláusula default (si_no).
45
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
4 SUBPROGRAMAS: PROCEDIMIENTOS Y FUNCIONES
4.1 Programación modular
El diseño descendente resuelve un problema efectuando descomposiciones en otros
problemas más sencillos a través de distintos niveles de refinamiento. La programación
modular consiste en resolver de forma independiente los subproblemas resultantes de una
descomposición.
La programación modular completa y amplía el diseño descendente como método de
resolución de problemas y permite proteger la estructura de la información asociada a un
subproblema.
Cuando se trabaja de este modo, existirá un algoritmo principal o conductor que transferirá el
control a los distintos módulos o subalgoritmos, los cuales, cuando terminen su tarea,
devolverán el control al algoritmo que los llamó. Los módulos o subalgoritmos deberán ser
pequeños, seguirán todas las reglas de la programación estructurada y podrán ser
representados con las herramientas de programación habituales.
El empleo de esta técnica facilita notoriamente el diseño de los programas. Algunas ventajas
significativas son:
Varios programadores podrán trabajar simultáneamente en la confección de un
algoritmo, repartiéndose las distintas partes del mismo, ya que los módulos son
independientes.
Se podrá modificar un módulo sin afectar a los demás.
Las tareas, subalgoritmos, sólo se escribirán una vez, aunque se necesiten en
distintas ocasiones en el cuerpo del algoritmo.
Existen dos tipos de subalgoritmos: funciones y procedimientos.
4.2 Funciones
Una función toma uno o más valores, denominados argumentos o parámetros actuales y,
según el valor de éstos, devuelve un resultado en el nombre de la función. Para invocar a
una función se utiliza su nombre seguido por los parámetros actuales o reales entre
46
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
paréntesis en una expresión. Es decir que se podrá colocar la llamada a una función en
cualquier instrucción donde se pueda usar una expresión.
Por ejemplo:
escribir(raíz2(16))
y si la función se llama f y sus parámetros son p1, p2 y p3
escribir(f (p1, p2, p3))
Cada lenguaje de programación tiene sus propias funciones incorporadas, que se denominan
internas o intrínsecas. Se considerarán como internas únicamente las más básicas y
comunes a casi todos los lenguajes. Si las funciones estándar no permiten realizar el tipo de
cálculo deseado será necesario recurrir a las funciones externas, que definiremos mediante
una declaración de función.
4.2.1 Declaración de funciones
Las funciones, como subalgoritmos que son, tienen una constitución similar a los algoritmos.
Por consiguiente, una función constará de:
Cabecera, con la definición de la función.
Cuerpo de la función.
Dentro del cuerpo de la función estará el bloque de declaraciones y el bloque de
instrucciones. En este bloque se debe incluir una instrucción devolver que recibe un valor
para devolverlo al algoritmo llamador.
Para que las acciones descritas en una función sean ejecutadas se necesita que ésta sea
invocada, y se le proporcionen los argumentos necesarios para realizar esas acciones. En la
definición de la función deberán figurar una serie de parámetros, denominados parámetros
formales y en la llamada a la función se establece una correspondencia uno a uno y de
izquierda a derecha entre los parámetros actuales y los formales. En el cuerpo de la función
se utilizarán los parámetros formales cuando se quiera trabajar con información procedente
del programa llamador.
El pseudocódigo correspondiente a una función es:
47
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
<tipo_de_dato> función <nombre de función>(lista_de_parámetros_formales)
[declaraciones locales]
inicio
……..
……..
……..
devolver(<expresión>)
fin_función
4.3 Procedimientos
Un procedimiento es un subalgoritmo que realiza una tarea específica y que puede ser
definido con 0, 1 o N parámetros. Tanto la entrada de información al procedimiento como la
devolución de resultados desde el procedimiento al programa llamador se realizarán a través
de los parámetros. El nombre de un procedimiento no está asociado a ninguno de los
resultados que obtiene.
La invocación a un procedimiento se realiza con una instrucción llamar_a o bien
directamente con el nombre del procedimiento. Es decir:
[llamar_a]<nombre_procedimiento>[(lista_de_parámetros_actuales)]
No existe obligatoriedad en los parámetros actuales
4.3.1 Declaración de procedimientos
La declaración de un procedimiento es similar a la de una función. Las pequeñas
diferencias son debidas a que el nombre del procedimiento no se encuentra asociado a
ningún resultado.
La declaración de un procedimiento expresada en pseudocódigo es:
48
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
procedimiento <nombre_procedimiento>[(lista_de_parámetros_formales)]
[declaraciones locales]
inicio
......
......
......
fin_procedimiento
4.4 Estructura general de un algoritmo
algoritmo <nombre_algoritmo>
const
<nombre_de_constante1>=valor1
var
<nombre_del_tipo>:<nombre_de_variable1>[,<nombre_de_variable2>,...]
.............................................................
//Los datos han de ser declarados antes de poder ser utilizados
inicio
<acción1>
<acción2>
llamar_a<nombre_de_procedimiento>[(lista_de_parámetros_actuales)]
// la llamada a la función ha de realizarse en una expresión
escribir(<nombre_de_función> (lista_de_parámetros_actuales))
//Se utilizará siempre la sangría en las estructuras
//selectivas y repetitivas.
.........
<acciónN>
fin
procedimiento <nombre_procedimiento>[(lista_de_parámetros_formales)]
[ declaraciones locales ]
inicio
...
...
...
fin_procedimiento
<tipo_de_dato> función <nombre_función>(lista_de_parámetros_formales)
// el <tipo_de_dato> devuelto por la función es un tipo estándar
[ declaraciones locales ]
inicio
......
......
devolver(<expresión>)
fin_función
49
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
4.5 Paso de parámetros
Cuando un programa llama a un procedimiento o función se establece una correspondencia
entre los parámetros actuales y los formales. Existen dos formas para establecer la
correspondencia de parámetros:
Posicional. Emparejando los parámetros reales y formales según su posición en las
listas. Esto requiere que ambas listas tengan el mismo número de parámetros y que
los que se van a emparejar coincidan en el tipo. En la definición del subprograma
deberá reflejarse siempre de qué tipo es cada uno de los parámetros formales.
(E <tipo_de_dato>:<nombre1_de_parámetro_formal>...)
El tipo de dato debe ser estándar o haber sido definido de antemano. Si los parámetros
formales se separan por comas es necesario, aunque no suficiente, que tengan el mismo
tipo. Si su tipo fuera distinto habría que poner:
(E <tipo_de_dato1>: <nombre1_de_parámetro_formal>;
E <tipo_de_dato2>: <nombre2_de_parámetro_formal>)
Correspondencia por el nombre explícito. En las llamadas se indica explícitamente
la correspondencia entre los parámetros reales y formales.
Dado que la mayor parte de los lenguajes usan exclusivamente la correspondencia
posicional, éste será el método que se seguirá en la mayoría de los algoritmos. Al hablar de
los procedimientos se decía que devuelven resultados al programa principal a través de los
parámetros, pero que también pueden recibir información, desde el programa principal, a
través de ellos. Esto nos lleva a una clasificación de los parámetros en:
Parámetros de entrada: Permiten únicamente la transmisión de información desde el
programa llamador al subprograma.
Parámetros de salida: Sólo devuelven resultados.
Parámetros de entrada/salida: Actúan en los dos sentidos, tanto mandando valores
al subprograma, devolviendo resultados desde el subprograma al programa llamador.
50
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
En los algoritmos, se debe especificar en la definición del subprograma el comportamiento
de cada uno de los parámetros. Para ello se empleará la siguiente terminología:
E equivaldría a parámetro de entrada.
S querrá decir parámetro de salida.
E/S parámetro de entrada/salida
Una función va a tener la posibilidad de devolver valores al programa principal de dos
formas:
• Como valor de la función.
• A través de los parámetros.
Un procedimiento sólo podrá devolver resultados a través de los parámetros, de modo que al
codificar el algoritmo se ha de tener mucho cuidado con el paso de parámetros, siendo
preciso conocer los métodos de transmisión que posee el lenguaje, para poder conseguir el
funcionamiento deseado. Los lenguajes suelen disponer de:
Paso por valor: Los parámetros formales correspondientes reciben una copia de los valores
de los parámetros actuales; por tanto los cambios que se produzcan en ellos por efecto del
subprograma no podrán afectar a los parámetros actuales y no se devolverá información al
programa llamador. Los parámetros resultarían de entrada, E.
Paso por valor resultado: Al finalizar la ejecución del subprograma los valores de los
parámetros formales se transfieren o copian a los parámetros actuales.
Paso por referencia: Lo que se pasa al procedimiento es la dirección de memoria del
parámetro actual. De esta forma, una variable pasada como parámetro actual es compartida;
es decir, se puede modificar directamente por el subprograma. Los parámetros serían de
entrada/salida, E/S.
4.6 Variables globales y locales
Una variable es global cuando el ámbito en el que dicha variable se conoce es el programa
completo. Se consideran como variables globales aquellas que hayan sido declaradas en el
programa principal y como locales las declaradas en el propio subprograma. Toda variable
que se utilice en un procedimiento debe haber sido declarada en el mismo. De esta forma
todas las variables del procedimiento serán locales y la comunicación con el programa
51
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
principal se realizará exclusivamente a través de los parámetros. Al declarar una variable en
un procedimiento no importa que ya existiera otra con el mismo nombre en el programa
principal; ambas serán distintas y, cuando nos encontremos en el procedimiento, sólo tendrá
vigencia la declaración que hayamos efectuado en él. Trabajando de esta forma
obtendremos la independencia de los módulos.
4.7 Recursividad
Un objeto es recursivo si forma parte de sí mismo o interviene en su propia definición. El
instrumento necesario para expresar los programas recursivamente es el subprograma. La
mayoría de los lenguajes de programación admiten que un procedimiento o función haga
referencia a sí mismo dentro de su definición, denominada recursividad directa.
Para comprender la recursividad se deben tener en cuenta las premisas:
- Un método recursivo debe establecer la condición o condiciones de salida.
- Cada llamada recursiva debe aproximar hacia el cumplimiento de la/las condiciones de
salida.
- Cuando se llama a un procedimiento o función los parámetros y las variables locales
toman nuevos valores, y el procedimiento o función trabaja con estos nuevos valores y
no con los de anteriores llamadas.
- Cada vez que se llama a un procedimiento o función los parámetros de entrada y
variables locales son almacenados en las siguientes posiciones libres de memoria y
cuando termina la ejecución del procedimiento o función son accedidos en orden inverso
a como se introdujeron.
- El espacio requerido para almacenar los valores crece conforme a los niveles de
anidamiento de las llamadas.
- La recursividad puede ser directa e indirecta. La recursividad indirecta se produce
cuando un procedimiento o función hace referencia a otro el cual contiene, a su vez, una
referencia directa o indirecta al primero.
52
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Taller No. 3
1. Realizar una función que permita intercambiar el valor de dos variables.
2. Realizar una función que permita obtener el término n de la serie de Fibonacci
3. Implementar una función que permita devolver un valor entero, leído desde teclado,
comprendido entre dos límites que introduciremos como parámetro.
4. Diseñar una función que permita obtener el valor absoluto de un número
5. Realizar una función que obtenga la división entera y el resto de la misma utilizando
únicamente los operadores suma y resta.
6. Diseñar un procedimiento que permita convertir coordenadas polares (radio, ángulo)
en cartesianas (x,y)
x = radio * cos(ángulo)
y = radio* sen(ángulo)
7. Diseñe una función que permita obtener el factorial de un número entero positivo.
8. Diseñar una función que permita obtener el máximo común divisor de dos números
mediante el algoritmo de Euclides.
9. Realizar una función que permita saber si una fecha es válida.
10. Implementar una función que permita hallar el valor de Xy, siendo X un número real e y
un entero.
11. Realizar tres funciones que permitan hallar el valor de pi mediante las series
matemáticas siguientes:
12. Realizar un subprograma que calcule la suma de los divisores de n distintos de n.
13. Dos números son amigos, si cada uno de ellos es igual a la suma de los divisores del
otro.
Por ejemplo, 220 y 284 son amigos, ya que:
53
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Suma de divisores de 284 : 1 + 2 + 4 + 71 + 142 = 220
Suma de divisores de 220: 1 + 2 + 4 + 5 + 10 + 11 + 20 + 22 + 44 + 55 + 110 = 284
Diseñe un algoritmo que muestre todas las parejas de números amigos menores o
iguales que m, siendo m un número introducido por teclado.
14. El número de combinaciones de m elementos tomados de n en n es:
Diseñe una función que calcule esta combinatoria.
15. Implemente tres funciones que permitan averiguar los valores de ex, cos(x) y sen(x) a
partir de las series siguientes:
16. Implementar una función Redondeo(a,b), que devuelva el número real a redondeado a
b decimales.
17. Realice un algoritmo que transforma un número introducido por teclado en notación
decimal a romana. El número será entero y positivo y no excederá de 3000.
18. Escribir una función recursiva que calcule el factorial de un número entero positivo.
19. Escriba una función recursiva que calcule la potencia de un número entero positivo.
20. Escribir un procedimiento recursivo que escriba un número en base 10 convertido a
otra base entre 2 y 9.
54
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
5 ESTRUCTURAS DE DATOS (ARRAYS Y REGISTROS)
5.1 Datos estructurados
Una estructura de datos es una colección de datos que se caracterizan por su organización y
las operaciones que se definen en ella. Los datos de tipo estándar pueden ser organizados
en diferentes estructuras de datos: estáticas y dinámicas.
Las estructuras de datos estáticas son aquellas en las que el espacio ocupado en
memoria se define en tiempo de compilación y no puede ser modificado durante la ejecución
del programa; por el contrario, las estructuras de datos dinámicas son aquellas en las
cuales el espacio asignado en memoria puede ser modificado en tiempo de ejecución.
Entre las estructuras de datos estáticas se encuentran:
Arrays
Registros
Cadenas
Conjuntos
Archivos
Las estructuras de datos dinámicas más conocidas son:
Listas
Árboles
Grafos
5.2 Arrays
Conocidos también como arreglos unidimensionales (vectores) o multidimensionales
matrices). Un array es una colección de datos del mismo tipo, que se almacena en
posiciones consecutivas de memoria y reciben un nombre común. Para referirse a un
determinado elemento de un array se deberá utilizar un índice, que especifique su posición
relativa en el array.
55
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
5.2.1 Arrays unidimensionales
Todo dato a utilizar en un algoritmo ha de haber sido previamente declarado. Los arrays no
son una excepción y lo primero que se debe hacer es crear el tipo, para luego poder declarar
datos de dicho tipo. Al ser un tipo estructurado, la declaración se hará en función de otro tipo
estándar o previamente definido, al que se denominará tipo base, por ser todos los
elementos constituyentes de la estructura del mismo tipo.
56
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
Todos los elementos del vector podrán seleccionarse arbitrariamente y serán igualmente
accesibles. Se les referenciará empleando un índice que señale su posición relativa dentro
del vector. Si <nombre_del_vector> fuera vect al elemento enésimo del array se le
referenciaría por vect[n], siendo n un valor situado entre el límite inferior (liminf) y el límite
superior (limsup). Los elementos podrán ser procesados como cualquier otra variable que
fuera de dicho tipo_base.
5.2.2 Arrays bidimensionales
Un array bidimensional es un vector de vectores; se denomina también matriz o tabla. Es
por tanto un conjunto de elementos del mismo tipo en el que el orden de los componentes es
significativo y en el que se necesitan especificar dos subíndices para poder identificar a cada
elemento del array.
57
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com
5.2 Registros
Un registro es un dato estructurado, formado por elementos lógicamente relacionados, que
pueden ser del mismo o de distinto tipo, a los que se denomina campos. Los campos de un
registro podrán ser de un tipo estándar o de otro tipo registro previamente definido.
En los lenguajes orientados a objetos el almacenamiento de información de diferentes tipos
con un único nombre suele efectuarse en clases, pero las clases no almacenan sólo campos
con el estado de un objeto, sino también su comportamiento. Algunos de estos lenguajes,
como C++ o C#, ofrecen además el tipo estructura. La estructura es similar a la clase en
Programación Orientada a Objetos e igual al registro en lenguajes estructurados como C o
Pascal.
Ejemplo de un dato de tipo registro podría ser el que permitiera almacenar la situación de un
punto en el plano, compuesta por dos números reales. De igual forma, si lo que se desea es
describir a una persona, se podría utilizar un dato de tipo registro para almacenar, agrupada,
la información más relevante.
Un tipo registro se declarará de la siguiente forma:
Para acceder a un determinado campo de un registro se utilizará, como suelen emplear la
mayoría de los lenguajes el nombre de la variable de tipo registro unido por un punto al
nombre del campo.
<nombre_de_variable>.<nombre_de_campo1>
Si los campos del registro fueran a su vez otros registros habrá que indicar:
<nombre_de_variable>.<nombre_de_campo1>.<nombre_de_campo_de_campo1>
Los datos de tipo registro se pueden pasar como parámetros tanto a procedimientos como a
funciones.
58
Msc. Nelson O. Cáceres M. |Lic. en Matemáticas y Física – Ingeniero de Sistemas |®2016 www.nelsoncaceres.com