0% encontró este documento útil (0 votos)
74 vistas174 páginas

NOTAS - Introducción A La Programación - Sergio Paez Rodea

Este documento proporciona una breve historia de la computación, desde las primeras máquinas mecánicas de suma y multiplicación hasta el desarrollo de las primeras computadoras electrónicas como la ENIAC y el modelo de von Neumann. También describe contribuciones clave como la máquina de Turing y cómo sentaron las bases para el software y hardware modernos.

Cargado por

Abraham Velasco
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
74 vistas174 páginas

NOTAS - Introducción A La Programación - Sergio Paez Rodea

Este documento proporciona una breve historia de la computación, desde las primeras máquinas mecánicas de suma y multiplicación hasta el desarrollo de las primeras computadoras electrónicas como la ENIAC y el modelo de von Neumann. También describe contribuciones clave como la máquina de Turing y cómo sentaron las bases para el software y hardware modernos.

Cargado por

Abraham Velasco
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

INTRODUCCIÓN A LA PROGRAMACIÓN

por

Ing. Sergio Páez Rodea

Departamento de Ingeniería Eléctrica

Universidad Autónoma Metropolitana

Unidad Iztapalapa

1ª Edición julio 2003


Última actualización: 15 de octubre del 2012
3
Índice

1.- BREVE RESUMEN HISTÓRICO DE LA COMPUTACIÓN …………………………...... 5

2.- SISTEMAS DE NUMERACIÓN .………………………………………………………...... 19

3.- REPRESENTACIÓN DE LA INFORMACIÓN ………………………………….............. 29

4.- DESCRIPCIÓN DE UNA COMPUTADORA ...…………………………………………... 45

5.- MÉTODO DE CASCADA ……………………………………………………..…………… 55

6.- ESTRUCTURA DE UN PROGRAMA, ENTRADAS, SALIDAS, ENUNCIADOS,


ENUNCIADOS DE ASIGNACIÓN, VARIABLES Y CONSTANTES ..………………..….... 63

7.- LÓGICA PROPOSICIONAL …………………………...………..…………………...……. 81

8.- ESTRUCTURAS DE CONTROL Y CONDICIONES ……………………....………….... 91

9.- PROCEDIMIENTOS Y FUNCIONES, PASO DE PARÁMETROS, VARIABLES


LOCALES Y VARIABLES GLOBALES …………………………………………………….. 111

10.- ¿QUÉ ES UN PROGRAMA?, ¿QUÉ ES PROGRAMAR?, MÉTODO DE


IMPLEMENTACIÓN DE ALGORITMOS ITERATIVOS, PSEUDOCÓDIGO,
REFINAMEITNOS SSUCESIVOS Y CODIFICACIÓN ……………………………………. 119

11.- AREGLOS, CADENAS Y REGISTROS ……….……………………………………… 137

12.- MODO GRÁFICO .……………………………………………………………………..... 147

13.- ARCHIVOS ………..……………………………………………………………………… 159

14.- MÉTODOS DE DESCOMPOSICIÓN, DESARROLLO DDESCENDENTE (TOP-


DOWN) Y PROGRAMACIÓN MODULAR .……………………………………………….... 165

APÉNDICE A …………………………………………………….……………………………. 171

BIBLIOGRAFÍA .……………………………………………………………………………….. 173

3
3
1.- BREVE RESUMEN HISTÓRICO DE LA COMPUTACION

La primer sumadora de engranes de la que se tiene noticia la inventó en 1623 un


profesor de hebreo, lenguas orientales, matemáticas, astronomía y geografía de la
Universidad de Tübingen, Alemania y que en sus ratos libres fungía como ministro
protestante llamado Wilheim Shickard (1592 – 1635). Su máquina estaba constituida por
una serie de engranes y era capaz de realizar las cuatro operaciones básicas con
números de seis dígitos, suma, resta, mutliplicación y división. Estaba basada en el
método de los huesos de Napier y en un mecanismo de sumas parciales. Contaba con
una campanita que sonaba cuando el resultado excedia de los seis dígitos. Se supo de
esta máquina por las cartas que Schickard sonstuvo con Johanes Kepler. Ggracias a una
hoja que se encontró el profesor Bruno, barón de Freytag-Löringhoff, profesor también de
la Universidad de Tübinge, pudo hacer una replica del prototipo original. Note que en
aquella época lo único con que se contaba para hacer máquinas era madera y metal.

Wilheim Schickard

Máquina de Schickard
Imágenes bajadas de: [Link]

3
La segunda máquina de engranes de la que se tiene noticia es la diseñada y
construida en 1640 por en matemático, físico, filósofo y teólogo francés Blas Pascal (1623
- 1662). Él diseñó y mandó construir esta máquina contando con tan solo diecinueve años
de edad para ayudar a su padre Etienne, el cual era recaudador de impuestos, por lo que
requería hacer gran cantidad de cálculos. Esta máquina estaba construida con engranes
y únicamente podía realizar sumas. Él mandó construir la primera, pero al no gustarle el
resultado se puso a estudiar mecánica para construirla él mismo. Produjo alrrededor de
cincuenta copias y trató de comercializalas, pero desafortunadamente el invento no tuvo
buena acojida, tal vez por que a veces se generaba un error en los acarreos. Actualmente
hay dos versiones de ella, una se encuentra en el Museo Zwinger, en Dresden, Alemania
y la otra se encuentra en el Museo de Artes y Oficios de París.

Blas Pascal
Imagen bajada de: [Link]

Máquina de Engranes
Imagen bajada de: [Link]

3
El tercer antecedente de la computadora fue un diseño que nunca llegó a
construirse pero que mostraba ideas bastante interesantes. Charles Babbage (1791 -
1871) fue un matemático inglés que diseñó lo que él llamó máquina analítica. A esta
máquina se le podía programar una función de cálculo, la cual, una vez programada era
fácil pedirle que calculara la función de cualquier argumento que se le suministrara. Cada
vez que fuera necesario calcular otra función sería necesario reprogramar la máquina.

Charles Babbage
Imagen bajada de:
[Link]

3
Un concepto matemático que resultó ser de gran utilidad para el área de la
computación fue la Máquina de Turing. Desde su juventud el matemático inglés Alan
Mathison Turing (1912 - 1954) tuvo la inquietud de crear una máquina que incorporara
inteligencia. Desde 1928 aproximadamente Turing estuvo trabajando con un problema
llamado problema del paro o the halting problem en donde se requería saber si existían
algoritmos que no terminaran en un tiempo finito. Para resolver este problema era
necesaria una máquina abstracta en la que se pudieran hacer representaciones de la
realidad a la que Turing llamó Máquina de Turing o Turing Machine (TM). Luego ideó otra
máquina capaz de representar cualquier otra máquina incluyéndose a si misma a la que
llamó Máquina Universal de Turing o Universal Turing Machine (UTM). Con el juego de
dos Máquinas Universales, una codificada dentro de otra Turing resolvió el problema del
paro y en 1936 demostró matemáticamente que existen procesos para los cuales no es
posible decidir si terminarán o no en un tiempo finito, llamados procesos indecidibles.

Alan Mathison Turing


Copiado del Libro Introducción a la Computación y a la Programación Estructurada
Guillermo Levine Gutierrez, Mc Graw Hill, 2ª Edición

Este concepto resultó de un potencial inimaginado ya que conceptualmente en


estas máquinas se podía representar cualquier aspecto de la realidad y cualquier proceso
por complejo que este fuera, generando la pregunta filosófica ¿Es posible hacer
representaciones completas de nuestro mundo o de nuestro universo? Estos temas han
servido de simiente para películas de ciencia ficción como The Matrix.

Turing fue solicitado para ayudar en el diseño de una máquina llamada "Bomba"
que exploraba las combinaciones posibles generadas por la máquina codificadora
alemana llamada "Enigma". La Bomba fue una máquina de propósito particular para
descifrar códigos construida electromecánicamente con relés, los cuales son dispositivos
electromecánicos.

3
Turing también trabajó en el desarrollo de la máquina llamada "Colossus" (que
algunos consideran el primer ordenador electrónico) que ya funcionaba con válvulas
electrónicas (tubos de vacío o bulbos) en lugar de relés; gracias a ella los británicos
pudieron mantener alejados a los submarinos alemanes de los barcos de suministro que
cruzaban el Atlántico.

Turing tenía el interés de crear una máquina con la cual pudiera romper los
códigos secretos a una mayor velocidad, lamentablemente nunca fue apoyado para
materializar su idea, no obstante, sus trabajos sirvieron más adelante para desarrollar los
lenguajes de programación y sentó las bases de la Teoría Matemática de la Computación
y de la Inteligencia Artificial.

Alan Turíng no recibió en vida, ni ha recibido reconocimiento alguno de la sociedad


a la que tanto ayudó en los momentos más difíciles, la sociedad británica.

Existe una controversia acerca de quién o quienes crearon la primer computadora


electrónica de la história. Una versión dice que en 1947 un equipo dirigido por los
ingenieros John Mauchly y John Eckert de la Universidad de Pennsylvania construyeron
una máquina electrónica llamada Integrador y Calculador Numerico Electrónico o
Electronic Numerical Integrator And Calculator (ENIAC) la cual trabajaba con tubos de
vacío comúnmente llamados bulbos.

John Mauchly
Imagen bajada de algún lugar de la red

3
John Eckert
Imagen bajada de algún lugar de la red

Imagen bajada de:


[Link]

Esta máquina presentaba un severo inconveniente, los programas se tenían que


alambrar en la memoria de programa por lo que un matemático húngaro llamado John
von Neumann (1903 -1957) que se había integrado al equipo y que había sido colega de
Turing propuso el siguiente cambio. En el nuevo modelo los programas podrían
almacenarse como datos en la memoria de la computadora dando lugar al software (del
inglés soft suave y ware losa) ya que se programaba de manera a la que ellos llamaron
suave, y no con alambres. Esto dio lugar a otro nuevo término, el hardware (del inglés
hard duro y ware losa) con el cual hacían referencia a los fierros de la máquina, es decir,
a la parte material de la computadora. A partir de ese momento una computadora estuvo
compuesta fundamentalmente de dos partes, el software y hardware. Por tal razón, a éste
modelo se le dio su nombre, Modelo de von Neumann y es el modelo que aún siguen los
diseãdores de las computadoras y es también por esto que es considerado el padre de
las computadoras. A ésta nueva máquina se le dio el nombre de Computadora de
Variable Discreta Electrónica o Electronic Discrete Variable Computer (EDVAC).

3
John von Neumann
Copiado del Libro Introducción a la Computación y a la Programación Estructurada
Guillermo Levine Gutierrez, Mc Graw Hill, 2ª Edición

Con la terminación de la segunda guerra mundial se vino el problema de como


explotar comercialmente este logro, ya que la computadora resultó ser muy útil para
almacenar, procesar y acceder grandes volúmenes de información. Las primeras
aplicaciones comerciales fueron administrativas. En 1951 aparece la primer computadora
comercial, la UNIVAC I (UNIVersAl Computer) fabricada por la compañía UNIVAC y más
tarde la IBM (International Business Machines) que fue una empresa originalmente
fundada por Herman Hollerith (1860-1929) el inventor de las tarjetas perforadas, entró al
mercado produciendo la IBM 701. Posteriormente surgieron otras compañías que también
entraron al mercado como Digital Equipment, Brroughs, Hewlett Packard, Control Data
Computers, Honeywell, International Computers Limited, Siemens, etc.

La primera generación de computadoras fue construída con bulbos. Con el


desarrollo de la tecnología, más adelante vino el advenimiento de los transistores que
reemplazaron a los bulbos, dando lugar a la segunda generación de computadoras, las
transistorizadas, las cuales se hicieron más pequeñas y eficientes. Después, los
científicos integraron varios transistores en un solo pedazo de silicio dando lugar a la
tercera generación de computadoras, la de los circuitos integrados. Y finalmente los
diseñadores pudieron integrar un procesador completo en un solo pedazo de silicio
aportando lo que hoy se conoce como microprocesador, dando lugar a la cuarta
generación de computadoras. Todo esto ha hecho que actualmente una computadora
no ocupe más que solo un pequeño espacio arriba de un escritorio a un costo accesible
para un gran número de personas.

Simultáneamente el área de software comenzó a tener importancia por sí misma y


también se fue desarrollando. Primero se crearon programas que pudieran traducir los
mnemónicos a su código correspondiente. Los mnemónicos son nombres que reciben
las instrucciones que puede ejecutar un procesador. Ejemplo, el mnemónico de la

3
operación “no operation” es “nop”. A estos programas se les llamó ensambladores y por
lo tanto al lenguaje que ensamblaban se le llamó ensamblador. Como había secciones
de código que se repetían se crearon las macros. >Las macros son secciones en código
ensamblador que se insertan cada vez que se invocan y por lo tanto a los programas que
ensamblaban el código se les llamó macro-ensambladores. Cada procesador que es
fabricado debe contar con su macro-ensamblador. Aunque ya no se programa en
ensamblador, aún así, cuando se requiere código super eficiente generalmente éste se
programa en ensamblador.

A finales de los 50's Jhon Backus lidereó un pequeño grupo de IBM que desarrolló
el primer lenguaje de alto nivel que podía ser traducido a lenguaje de máquina, este
lenguaje se llamó FORTRAN (Formula Translator) y su cualidad sorprendente era que los
científicos podían ahora escribir sus formulas casi de la misma manera en la que las
escriben en álgebra. Los físicos aún utlilizan este lenguaje.

En 1960 Jhon McCarty del Massachusetts Institute of Technology (MIT) crea Lisp
(List Processor) en donde un programa se ve como una lista y se programa a través de
funciones recursivas. Lisp es un lenguaje altamente abstracto.

En cuanto a los Sistemas Operativos, anteriormente estos se programaban en


ensamblador, esto era muy engorroso, así que comenzó la inquietud de crear lenguajes
de alto nivel para programarlos. Un investigador de los laboratorios Bell en los Estados
Unidos de Norteamérica se dio a la tarea de desarrollar un lenguaje de alto nivel pero que
a su vez pudiera tener acceso a los registros de la computadora y diseñó y construyó el
lenguaje al que él llamó “B”. Con este lenguaje construyó el nucleo (kernel) de un sistema
operativo de tiempo compartido (time shering) al que llamó Unix. La estrategía del tiempo
compartido consiste en tener gran cantidad de procesos dados de alta en la
computadora, todos ellos compartiendo el procesador. Como el procesador corre a gran
velocidad, es posible asignarle a cada proceso una rebanada de tiempo. Como el
procesador ejecuta el código a gran velocidad, los diferentes procesos solo perciben que
su resolusión va en avance. Mas adelante perfeccionaron el lenguaje diseñando y
construyendo el lenguaje “C” y reescribieron el código de Unix en C. Hay que reconocer
que C es un lenguaje en el cual los archivos que lo constituyen tienen una estructura bien
definida, el lenguaje es elegante y conserva su estilo, pero desafortunadamente es muy
críptico y ha sido fuertemente criticado por su laxitud en el manejo de las diferentes
representaciones de datos, además de que su compilador no es tan robusto en la
detección y marcado de los errores. C y Unix se convirtieron en lenguajes tan exitosos
que comensaron a ser utilizados por diferentes laboratorios y Universidades.

En 1983 un programador llamado Richard Stallman inició un movimiento llamado GNU el


cual proponía la creacion de software que no tuviera derechos, lo inverso al copyrigh,
llamándole software libre. A tal movimiento le llamo GNU el cual es un acrónimo recursivo
que quiere decir GNU is Not Unix. >

A principios de los 80's con la fabricación de procesadores en una pastilla,


llamados microprocesadores, comenzaron a aparecer computadoras personales. Con
esto, el sueño de que las personas pudieran tener una computadora en casa se comenzó

3
a hacer realidad. Aparecieron en el mercado una serie de computadoras personales que
tuvieron cierto éxito, como la Timex Sinclair y la TRS-80 de Radio Shack basadas en el Z-
80 de Zilog (microprocesador de 8 bits) y las famosas Apple basadas en el 6502 de
Motorota (también de 8 bits).

Al darse cuenta IBM del nicho que se estaba abriendo decidió entrar a la
competencia y sacó la Personal Computer (PC) basada en el 8088 de Intel, también de 8
bits, solo que se asoció con una compañía de software que se encargaría de elaborar el
sistema operativo de la máquina. Ésta empresa fue nada más y nada menos que
Microsoft la cual desarrolló el sistema operativo MS-Dos que corre en las PC compatibles
hasta la fecha. Microsoft pactó recibir los pagos por las licencias y es por esto que la
empresa se ha hecho inmensamente rica.

Con las ventanas la Xerox desarrolló una interfaz manual a la que llamó mouse
(del inglés mouse ratón) la cual poco a poco comenzaron a utilizar para la interfaz gráfica
de los sistemas operativos convirtiéndose en un instrumento estándar utilizado
actualmente en las computadoras.

Posteriormente Apple desarrolló su sistema de ventanas siendo tan eficiente que


Microsoft lo copió utilizándolo como interfaz gráfica del sistema operativo.

Poco después apareció el concepto de multimedia donde se buscaba aprovechar


todos los sentidos posibles para establecer comunicación con la computadora. Multimedia
consistía de aprovechar texto, imágenes y sonido. Esto hizo que se incluyera una tarjeta
de sonido a la computadora como un elemento estándar.

En los 90's apareció el concepto de realidad virtual el cual consistía en crear


ambientes virtuales en donde el usuario se sintiera inmerso en un ambiente artificial
creado por la computadora dando lugar a la creación de algunos filmes como Matrix. Los
simuladores crean ambientes de realidad virtual y está tecnología se ha empleado
también para los juegos de computadora y dio origen al termino virtual que actualmente
conocemos.

Las computadoras se han convertido en parte fundamental de la vida de la


humanidad ya que por su capacidad de ser reprogramadas pueden comportarse de
diferentes maneras, pueden trabajar como procesadores de palabra, terminales remotas,
simuladores, programas de entrenamiento, programas de cálculo, controladores de
equipos mecánicos, instrumentos de medición, analizadores, procesadores,
sintetizadores de imágenes, procesadores de texto, hojas de cálculo, bases de datos, y
en fin, tantas aplicaciones como el hombre pueda concebir.

Desde la década de los 80's las redes de computadora comenzaron a tomar auge
ya que las empresas requerían hacer un uso más eficiente de sus recursos apareciendo
diferentes topologías de red y diferentes marcas de redes como Novel y otras más.

La Agencia de Proyectos Avanzados de Investigación de Defensa (Defence


Advanced Research Projects Agency, DARPA) del Departamento de Defensa de los

3
Estados Unidos propuso un proyecto para hacer un protocolo abierto y así poder
interconectar máquinas de diferente marca. Este agencia propuso el Modelo OSI (Open
Systems Interconection) que es un modelo de siete capas en donde la capa de transporte
la maneja un protocolo de control, Transport Control Protocol (TCP) y la capa de enlace la
maneja el protocolo de internet, Internet Protocol (IP).

No. De Capa Nombre Controla


7 Aplicación Aplicaciones y Servicios
6 Destino Estructura Información
5 Sesión Control de Dialogo
4 Transporte Rompe los Mensajes
3 Red Ruteo
2 Enlace de Datos Errores
1 Física Bits

Modelo OSI

El proyecto fue exitoso y la agencia invitó a algunas Universidades a conectarse a


la red a la que llamaron Internet para compartir información útil para la investigación. Los
servicios que proporcionaba la red eran transferencia de archivos, terminal virtual y correo
electrónico.

Posteriormente apareció un navegador en modo texto llamado Mosaic. Más


adelante Tim BernersLee creo el lenguaje de hipertexto HiperText Meta Language
(HTML) el cual es un lenguaje para marcación de texto con el que se crearon páginas
web y navegadores dando lugar a la World Wide Web (Red Amplia Mundial) o www como
la conocemos actualmente.

Se creo un grupo para administrar la red y finalmente se permitió concesionar a


empresas comerciales para dar servicios de Internet. A estos concesionarios se les llamó
proveedores de servicios de Internet los cuales proporcionan conexiones, cuentas,
mantenimiento de páginas Web, dominios y otros servicios.

En la década de los 90's Netscape desarrolló el primer navegador en modo gráfico


para la red llamado así, Netscape y posteriormente Microsoft entró a la competencia con
Internet Explorer posicionándose como líder de los navegadores actualmente.

Esto ha hecho que el modem (modulador-demodulador) y las tarjetas de red se


hayan convertido en otros de los dispositivos estándar de las computadoras.

También apareció una nueva área de inversiones dando lugar al un nuevo índice
de cotizaciones de compañías de software llamado NASDAQ.

Con el advenimiento de las redes de computadoras estas están sirviendo no solo


para aplicaciones tradicionales, sino también como medio de comunicación masiva en el
mundo, de tal manera que es posible comunicarse a cualquier parte del mundo, correr

3
programas desde lugares remotos, transferir archivos, publicitar bienes y servicios,
información social y gubernamental, oír estaciones de radio, compartir música, etc.

Todo esto está revolucionando al mundo haciendo que el mundo sea cada vez
más pequeño en el sentido del acceso y el alcance de la información, por lo tanto
actualmente las computadoras no solo sirven como herramientas de cálculo, sino también
como herramientas para profesionistas, la oficina, el hogar y para conectarse al mundo.

3
3
EJERCICIOS CAPÍTULO 1 Fecha de entrega: ______________
Nombre (comenzando por el apellido): ________________________________________
1.- ¿Cuales son las máquinas que antecedieron la creación de la computadora? _______
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
2.- ¿Quién sentó las bases de la teoría matemática de la computación? ______________
_______________________________________________________________________
3.- ¿Cuando, donde y quienes fabricaron la primera computadora de la historia? _______
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
4.- ¿Qué nombre le dieron a ésta máquina y cual era su desventaja? ________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
5.- ¿Cual es el nombre del matemático húngaro que propuso un modelo en donde los
programas se manejan como datos? __________________________________________
6.- ¿Qué nombre recibió éste nuevo modelo? ___________________________________
_______________________________________________________________________
7.- ¿Cual es el nombre de la empresa que comenzó a comercializar este hallazgo
científico? _______________________________________________________________
8.- ¿Cuales fueron las etapas de evolución de las computadoras en cuanto a
componentes? ___________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
9.- .- ¿Cuales fueron las etapas de evolución de las computadoras en cuanto a software?
_______________________________________________________________________

3
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
10.- Liste cinco usos que se les puede dar a las computadoras:
______________________
_______________________________________________________________________
_______________________________________________________________________
11.- ¿Cual es la empresa que desarrolló el sistema operativo para las PC's de IBM?
_______________________________________________________________________
12.- ¿Cual es el nombre de la empresa que fabricó el primer navegador en modo gráfico
que apareció en la red? ____________________________________________________

3
2.- SISTEMAS DE NUMERACIÓN

Para que la computadora pudiera manejar la información fue necesario inventar


una manera de representarla físicamente. Las computadoras pueden almacenar
información en forma de voltajes. Un capacitor cargado proporciona un voltaje, y uno
descargado no. Los voltajes con los que trabajan las computadoras normalmente son 5 y
0 volts. Como los sistemas de numeración trabajan con símbolos y no con voltajes se le
asignó por convención al voltaje de 5 volts el símbolo "1" y al voltaje de 0 volts el símbolo
"0". Se hace la aclaración de que se habla de símbolos y no de números ya que como
veremos más adelante los sistemas de numeración se construyen con símbolos y no con
números, se forman números con los símbolos y los sistemas de numeración.

Un símbolo tiene cierto valor dependiendo de la base del sistema de numeración


que se esté manejando. Un símbolo es cualquier grafo bien definido. Para valores lógicos
se asignó, también por convención, "verdadero" a "1" y "falso" a "0".

A la celda que puede tomar valores de "0" ó "1" se le llama bit que quiere decir
dígito binario.

Ahora vamos a tratar los sistemas de numeración. Formemos el sistema de


numeración más simple. El sistema de numeración más simple es el que utiliza dos
símbolos, a éste sistema se le llama binario. Obviamente los dos símbolos que se
utilizarán son el "0" y el "1".

Construyamos los primeros números binarios.

0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1001
1010
1011
1100
1101
1110
1111

Observe que la primera columna varía de uno en uno, la segunda de dos en dos, la
tercera de cuatro en cuatro y así sucesivamente.

3
Para encontrar el correspondiente decimal de cualquier número de cualquier base
se hace lo siguiente:

Cada columna corresponde a un orden, el peso de cada columna se encuentra


elevando la base del sistema numérico al número de columna. El número de columna
comienza por el lado derecho y tiene el valor 0. O sea, para el sistema binario
tendríamos:

2n……… 24 23 22 21 20

con

20 = 1
21 = 2
22 = 4
23 = 8
24 = 16
.
.

Por lo tanto el número 01100112 equivale a:

1 x 20 + 1 x 21 + 1 x 24 + 1 x 25 = 1 + 2 + 16 + 32 = 5110

La base de un sistema de numeración es el número de símbolos con los que él


cuenta y se escribe como subíndice después de la cadena de símbolos. El sistema
decimal presenta muchas características que facilitan la manipulación de los números y
por esto se ha escogido como el estándar para los humanos aunque cabe mencionar que
no todas las culturas han utilizado el sistema base diez o decimal. Ya que éste es el
estándar se omite escribir la base por obviedad pero estrictamente hablando debería de
escribirse.

El siguiente sistema que nos interesa es el octal. Este sistema está formado por
ocho símbolos. Así tendríamos:

0
1
2
3
4
5
6
7
10
11
12

3
.
.

Por lo tanto el número 235748 equivale a:

4 x 80 + 7 x 81 + 5 x 82 + 3 x 83 + 2 x 84 = 4 + 56 + 320 + 1536 + 8192 = 1010810

con
80 = 1
81 = 8
82 = 64
83 = 512
84 = 4096
.
.

El siguiente sistema en importancia es el decimal y es con el que estamos más


familiarizados y la conversión es inmediata.

El último sistema que veremos es el hexadecimal y consta de dieciséis símbolos.


Es claro ver que si los símbolos usados en los sistemas de numeración son diez nos
harán falta seis símbolos. Estos símbolos los tomaremos de las letras bajo la siguiente
tabla:

Símbolo Decimal
A 10
B 11
C 12
D 13
E 14
F 15

Así el número 1C5B16 es:

1 x 163 + 12 x 162 + 5 x 161 + 11 x 160 = 7,25910


con
160 = 1
161 = 16
162 = 256
163 = 4096
164 = 65536
.
.

ya que B es una forma de simbolizar a 1110 y C a 1210 de acuerdo a la tabla anterior.

3
Si se agrupan los bits en grupos de tres es fácil convertir un número binario en
octal. Para facilitar las conversiones construiremos una tabla de los primeros dieciséis
números en los cuatro sistemas numéricos.

Binario Octal Decimal Hexadecimal


0000 0 0 0
0001 1 1 1
0010 2 2 2
0011 3 3 3
0100 4 4 4
0101 5 5 5
0110 6 6 6
0111 7 7 7
1000 10 8 8
1001 11 9 9
1010 12 10 A
1011 13 11 B
1100 14 12 C
1101 15 13 D
1110 16 14 E
1111 17 15 F

Tabla de los primeros dieciséis números en los cuatro sistemas numéricos

Agrupando bits es fácil pasar de binario a cualquier sistema de numeración cuya


base sea una potencia de 2, en este caso octal y hexadecimal. Para pasar de binario a
octal únicamente es necesario agrupar de tres en tres bits y usar la tabla anterior. Para
pasar de binario a hexadecimal únicamente es necesario agrupar de cuatro en cuatro
bits.

Ejemplo:

El número 1011011001112

101 101 100 111


en octal es: 5 5 4 78

1011 0110 0111


en hexadecimal es: B 6 716

Ahora, si queremos pasar un número en decimal a una base dada lo único que
tenemos que hacer es dividir el número entre la base dada tantas veces como se pueda
hasta que el siguiente cociente ya no se pueda dividir. Los residuos darán los factores en
orden inverso al que vayan apareciendo, y el último factor lo dará el último cociente.

3
Ejemplo: se desea convertir el siguiente número en decimal a hexadecimal

423510

Lo primero que tenemos que hacer es dividir subsecuentemente el número entre la


base a la que lo queremos convertir, en éste caso 16, por lo tanto tendríamos:

__264_
16 | 4235
103
75
11

_16_
16 | 264
8

_1_
16 | 16
0

_ 0_
16 | 1
1

Por lo tanto tenemos que 423510 equivale a 108B16

De esta forma podemos tener números en una determinada base y pasarlos a otra
base si así nos conviene.

Otro método para pasar un número decimal a binario consiste en poner una línea y
dividir el número en dos poniendo el residuo del lado derecho y el cociente en la parte
baja. Esto se repite hasta que el cociente sea cero, el número en binario es el número en
secuencia inversa en la que apareció, ejemplo:

213 |

3
106 | 1
53 | 0
26 | 1
13 | 0
6|1
3|0
1|1
0|1

Por lo tanto el número 21310 es 110101012

A continuación se muestran cuatro gráficas donde se muestra cual es el método


más adecuado para pasar de un sistema a otro. Note que no hay una sola manera de
pasar de un sistema a otro, es posible utilizar dos métodos en cascada, también es
posible regresar al mismo número por el sistema inverso o por otro camino.

3
3
3
EJERCICIOS CAPÍTULO 2 Fecha de entrega: ___________
Nombre (comenzando por el apellido): ________________________________________
La calificación se calcula sobre el número total de respuestas, en este caso, 30.
Agregue las operaciones en la parte de atrás.
1.- Utilizando el método de suma de potencias convierta los siguientes números de
binario, octal y hexadecimal a decimal:
110110112 _________________ 46728 _______________ E0F116 __________________
2.- Utilizando el método de divisiones sucesivas convierta los siguientes números de
decimal a binario, octal y hexadecimal:
4010 _____________________ 8010 __________________ 10010 _____________________________
3.- Utilizando el método de agrupamiento convierta los siguientes números al sistema de
numeración octal y hexadecimal.

________________ _________________ _________________


1100112 0100112 1110012
________________ _________________ _________________

4.- Utilizabdo el método de desagrupamiento convierta los siguientes números al sistema


de numeración binario.

208 268 758


________________________ ___________________ ____________________

6D16 A216 3E16


______________________ ____________________ ____________________

3
5. – Utilizando el método de divisiones sucesivas convierta los siguientes números a
hexadecimal, binario y octal.
14710 15810 13610
______________________16 ___________________16 ___________________16
______________________2 ___________________2 ____________________2
______________________8 ___________________8 ____________________8
6.- Utilzando el método de suma de potencias convierta los siguiente números de binario,
octal y hexadecimal a decimal:
101100112 _______________10 33338 _____________10 ABCD16 _________________10

3
3.- REPRESENTACIÓN DE LA INFORMACIÓN

Como comentábamos, la información en la computadora se almacena en bits por


lo que fue necesario establecer una forma de representar los números dentro de ella. En
un principio cada fabricante decidía como iba a representar los números, pero con el paso
del tiempo se adoptó un estándar.

NÚMEROS ENTEROS

Los números que son más fáciles de representar en una computadora son los
números enteros ya que para su almacenaje y su recuperación los procedimientos son
sencillos. Es imposible representar en la computadora al conjunto infinito de números, ya
que para esto se requeriría una memoria infinita, además no todos los números son
usados, por lo que acortando el intervalo se puede tener una representación bastante útil.
La representación del signo se puede hacer tomando el primer bit a la izquierda como el
signo, un 0 representa un signo positivo y un 1 representa un signo negativo. El número
de bytes razonable para un buen intervalo es de 16. Un byte está constituido por ocho
bits. Por lo tanto, un número entero está representado generalmente por dos bytes. El
intervalo de números que podemos representar con dieciséis bits es [+32,767, -32,767]
pasando por el 0.
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

214+213+212+210+29+28+27+26+25+24+23+22+21+20 = 32,767

y como el signo es positivo, entonces este número en binario representa al +32,767.

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

= +0

Los números negativos se almacenan en su representación de complemento a 2 (‘2).

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1

= -32,767

Es importante hacer ver al lector que cada vez que ingresa un número a la
computadora entra a una memoria donde una vez capturado como cadena de símbolos
se procesa para ser almacenado en forma binaria y cada vez que se desea ver un
número en la pantalla la computadora tiene que hacer el proceso inverso para mostrarlo

3
como una cadena de símbolos. Las operaciones aritméticas dentro de la computadora se
realizan en binario.

Normalmente la memoria de las computadoras está organizada en secuencias de


bytes. Cada vez que se reserva espacio para un número se almacena en una tabla la
dirección de comienzo del número por lo que la computadora puede saber donde
comienza este en todo momento solo con consultar la tabla. Si el número abarca varios
bytes la lectura se puede hacer por secciones. El tamaño de la sección lo da la longitud
del canal de datos, si este es de 16 bits cada sección será de 16 bits, si es de 32, cada
sección será de 32 bits y así sucesivamente. Esto se hace para que la lectura de un
número se haga con el menor número de accesos a memoria posibles. A la longitud del
canal de datos de le llama longitud de palabra (word).

NÚMEROS EN REPRESENTACIÓN DE FUNTO FLOTANTE

Ya vimos como se representan los números enteros, pero resulta que hay
problemas en donde se manejan escalas mayores que las anteriores, ¿qué hacer? La
solución a éste problema son los números en notación científica o de punto flotante.
Éstos constan de dos partes, una que es la mantisa y otra que es el exponente. El
exponente se representa con un número entero y la mantisa con un número fraccionario
en donde el punto es imaginario y se representa a su lado izquierdo.

En lo general a la mantisa se le da una longitud de 42 bits, lo cual nos da


aproximadamente 12 cifras significativas y al exponente, como normalmente no es
excesivamente grande, se le da una longitud de seis bits, de tal forma que el espacio para
representar un número en punto flotante son generalmente 48 bit's o sea 6 bytes. Las
cifras significativas es una manera de medir la presición de un número. En un cálculo se
pueden requerir cierto número de cifras significativas, es decir, debe ser posibloe confiar
en esas cifras en un resultado. Por ejemplo 3.1416 consta de cinco cifras significativas.
Entre más cifras se requieren el cálculo y el almacenamiento serán más costosos.

Con ésta representación podremos representar números de 0.000000000001 X 10


-32
a 0.999999999999 X 10+32 aproximadamente, aunque el procedimiento ReadLn de
TurboPascal permite números de 1.000000 x 10 -38 a 1.000000 x 10+38. En TurboPascal el
formato para ingresar un número en notación científica es: 1.000000e-38 a 1.000000e38
y las cifras significativas que proporciona son once en lugar de las doce, aunque
internamente son doce, esto se hace para que no se vea el redondeo de la última cifra o
para que no se confie en la doceava cifra por seguridad.

Por ejemplo si en TurboPascal se le da siguiente entrada a un entero:

1e-38

y después se escribe la bariable el valor que se escribe será:

1.0000000000E-38

3
y si se da la siguiente entrada:

1e38

el valor que se escribe será:

1.0000000000E38

con la entrada:

0.555555555555

el valor que se escribe será:

5.5555555555E-1

pero si la entrada es:

0.5555555555555

el valor que se escribe será:

5.55555555556E-1

Observe que cuando se ingresan 13 cifras significativas se efectúa un redondeo a


12 cifras significativas a la hora de almacenar el dato, claro que a la hora de desplegar el
dato este redondeo se hará evidente.

Por lo tanto se puede ver que el procedimiento de entrada y el procedimiento de


salida hacen una transformación a la información representada en memoria, primero para
poder almacenarla en la representación dada y luego para que se pueda ver de la forma
más útil para el usuario.

En general la forma de medir la precisión de los cálculos se hace a través de cifras


significativas. Las cifras significativas que se alcanzan con una representación está dada
en base a los órdenes de magnitud completos en decimal que cubre la representación.

Ejemplo: con un bit no cubrimos ni siquiera un orden de magnitud ya que el


número de combinaciones que tendíamos es dos, "0" y "1".

Con dos bits ya tenemos cuatro combinaciones pero todavía no cubrimos un


orden, para cubrir un orden necesitamos rebasar una potencia de 10.

Con tres bits tenemos ocho combinaciones por lo que todavía no alcanzamos un
orden de magnitud.

3
Con cuatro bits ya tenemos 16 combinaciones y como ya rebasamos la primera
potencia de diez, es decir, 101 ya podemos representar un orden, aunque nos sobrarán
seis combinaciones, lo que quiere decir que con cuatro bits en realidad podemos
representar poco más de un orden de magnitud.

Debido a que las potencias en binario no coinciden con las potencias de diez las
representaciones con cierto número de bits no representan órdenes de magnitud
cerrados en decimal por lo que los órdenes sólo nos dan un parámetro cualitativo para
medir la precisión de una determinada representación.

Así, existen dos formas de evaluar una representación, una es por el intervalo de
los números representados y otra por las cifras significativas o los ordenes de magnitud
cubiertos.

Proporcionamos la siguiente tabla la cual ayuda a encontrar los órdenes de


magnitud que se pueden representar con cierto número de bits.

3
Número de bits Número de combinaciones
1 2
2 4
3 8
4 16
5 32
6 64
7 128
8 256
9 512
10 1K
11 2K
12 4K
13 8K
14 16K
15 32K
16 64K
17 128K
18 256K
19 512K
20 1M
21 2M
22 4M
23 8M
24 16M
25 32M
26 64M
27 128M
28 256M
29 512M
30 1KM
31 2KM
32 4KM
33 8KM
34 16KM
35 32KM
36 64KM
37 128KM
38 256KM
39 512KM
40 1MM
41 2MM
42 4MM

3
Observe que cada diez bits el número de combinaciones crece en tres órdenes de
magnitud. Se puede obtener la siguiente tabla:

Número de Bits Ordenes de magnitud


10 3
20 6
30 9
40 12

Por lo tanto con el número de bits se puede obtener el número de ordenes de


magnitud de los números representados dándonos ésto un estimado de la precisión que
vamos a obtener.

La representación de los números negativos se hace generalmente con el


complemento a dos ('2). Esta representación tiene la cualidad de que la suma funciona no
importando si algún número o los dos son negativos.

Para ilustrar cómo se obtiene el complemento a dos de un número primero


mostraremos como obtener el complemento a uno ('1).

Para obtener el complemento a uno lo único que hay que hacer es cambiar los 1's
por 0's y viceversa, ejemplo:

El complemento a 1 de: 01100110 +102


es: 10011001

El complemento a 2 se obtiene sumándole 1 al complemento a 1, ejemplo:

10011001
+ 00000001
10011010 -102
Para mostrar que son opuestos en signo los números los sumamos y obtenemos:

01100110 +102
+ 10011010 + -102
100000000 0

el primer 1 no se toma en cuenta.

Un truco para obtener el complemento a dos de un número es dejar los primeros


ceros a la derecha del número iguales, dejar el primer 1 igual y cambiar los símbolos
restantes a la izquierda por su complemento, ejemplo:

00110100 +52
11001100 -52

3
Esto se puede extender a números de n bytes.

La mantisa se representa con números fraccionarios. Ejemplo: Supongamos que tenemos


una mantisa de 8 bits
S 2-1 2-2 2-3 2-4 2-5 2-6 2-7
0 1 0 0 0 0 0 0

representa 1 x 2 -1 = ½ = 0.5

S 2-1 2-2 2-3 2-4 2-5 2-6 2-7


0 1 1 0 0 0 0 0

representa 1 x 2 -1 + 1 x 2 -2 = ½ + 1/4= 0.5 + 0.25 = 0.75

S 2-1 2-2 2-3 2-4 2-5 2-6 2-7


0 1 0 1 0 0 0 0

representa 1 x 2 -1 + 1 x 2 -3 = ½ + 1/8= 0.5 + 0.125 = 0.625

de tal manera que es posible aproximar un número con fracciones de potencias de dos.
Es claro que habrá números que sean exactos, pero habrá números que no. Si un
número es la suma de algunas o todas las fracciones se representará exacto, de otra
forma se hará una aproximación. Con 42 bits la aproximación será funcional.
La representación de la mantisa negativa no se hace en complemento a dos.
Generalmente se hace en representación con signo, es decir la mantisa es positiva
siempre, únicamente el signo es positivo o negativo. Esto hace que las operaciones de
números en punto flotante se lleven más tiempo. Actualmente los procesadores constan
de una unidad que hace las operaciones en punto flotante para hacer más rápido este
proceso.

CARACTERES ALFANUMÉRICOS

Con estas dos representaciones cubrimos lo fundamental en cuanto a números,


pero queda un problema pendiente ¿Cómo manejar símbolos alfanuméricos en una
computadora? Éste problema se resolvió asignando un número binario a un símbolo
alfanumérico. En un principio también cada fabricante diseñó su tabla de símbolos, pero
esto tenía un gran problema, que un archivo alfanumérico creado en una computadora de
un fabricante x no podía ser leído en otra computadora de un fabricante y. Esto generó
que se trabajara en un estándar para que los archivos pudieran ser leídos
independientemente del fabricante de la computadora. Así es como nació el código ASCII
(American Standard Code for Information Interchange). Los códigos también requieren
caracteres de control que son caracteres invisibles, estos son para el manejo de la
pantalla y para protocolos de comunicación. En un principio el código únicamente contaba
con siete bits, pero dado que es más práctico utilizar ocho se creó el ASCII extendido que
consta de 8 bits con 255 símbolos y carácter es de control.

3
La tabla del código ASCII extendido es la siguiente:

Decimal Hexadecimal ASCII

0 0 NULL null
1 1 SOH start of heading
2 2 STX start of text
3 3 ETX end of text
4 4 EOT end of transmission
5 5 ENQ enquiry solicitud de envío
6 6 ACK acknoledge reconocimiento
7 7 BELL bell campana
8 8 BS backspace retroceso
9 9 HT horizontal tab tabulador horozpntal
10 A LF line feed salto de línea
11 B VT vertical tab tabulador vertical
12 C FF form feed nueva página
13 D CR cariage return regreso de carro
14 E SO shift out
15 F SI shift in
16 10 DLE data link escape
17 11 DC1 device control 1
18 12 DC2 device control 2
19 13 DC3 device control 3
20 14 DC4 device control 4
21 15 NAK negative acknowledge
22 16 SYN synchronous idle
23 17 ETB end of trans. block
24 18 CAN cancel
25 19 EM end of medium
26 1A SUB substitute
27 1B ESC escape escape
28 1C FS file separator
29 1D GS group separator
30 1E RS record separator
31 1F US unit separator
32 20 SPACE Espacio
33 21 !
34 22 "
35 23 #
36 24 $
37 25 %
38 26 &
39 27 '
40 28 (
41 29 )
42 2A *

3
43 2B +
44 2C ,
45 2D -
46 2E .
47 2F /
48 30 0
49 31 1
50 32 2
51 33 3
52 34 4
53 35 5
54 36 6
55 37 7
56 38 8
57 39 9
68 3A :
69 3B ;
60 3C <
61 3D =
62 3E >
63 3F ?
64 40 @
65 41 A
66 42 B
67 43 C
78 44 D
79 45 E
70 46 F
71 47 G
72 48 H
73 49 I
74 4A J
75 4B K
76 4C L
77 4D M
78 4E N
79 4F O
80 50 P
81 51 Q
82 52 R
83 53 S
84 54 T
85 55 U
86 56 V
87 57 W
88 58 X
89 59 Y

3
90 5A Z
91 5B [
92 5C \
93 5D ]
94 5E ^
95 5F _
96 60 `
97 61 a
98 62 b
99 63 c
100 64 d
101 65 e
102 66 f
103 67 g
104 68 h
105 69 i
106 6A j
107 6B k
108 6C l
109 6D m
110 6E n
111 6F o
112 60 p
113 71 q
114 72 r
115 73 s
116 74 t
117 75 u
118 76 v
119 77 w
120 78 x
121 79 y
122 7A z
123 7B {
124 7C |
125 7D }
126 7E ~
127 7F DEL
128 80 Ç
129 81 ü
130 82 é
131 83 â
132 84 ä
133 85 à
134 86 å
135 87 ç
136 88 ê

3
137 89 ë
138 8A è
139 8B ï
140 8C î
141 8D ì
142 8E Ä
143 8F Å
144 90 É
145 91 æ
146 92 Æ
147 93 ô
148 94 ö
149 95 ò
150 96 û
151 97 ù
152 98 ÿ
153 99 Ö
154 9A Ü
155 9B ø
156 9C £
157 9D Ø
158 9E ×
159 9F ƒ
160 A0 á
161 A1 í
162 A2 ó
163 A3 ú
164 A4 ñ
165 A5 Ñ
166 A6 ª
167 A7 º
168 A8 ¿
169 A9 ®
170 AA Ñ
171 AB ½
172 AC ¼
173 AD ¡
174 AE «
175 AF »
176 B0
177 B1
178 B2
179 B3
180 B4
181 B5 Á
182 B6 Â
183 B7 À

3
184 B8 ©
185 B9
186 BA
187 BB
188 BC
189 BD ¢
190 BE ¥
191 BF
192 C0
193 C1
194 C2
195 C3
196 C4
197 C5
198 C6 ã
199 C7 Ã
200 C8
201 C9
202 CA
203 CB
204 CC
205 CD
206 CE
207 CF ¤
208 D0 ð
209 D1 Ð
210 D2 Ê
211 D3 Ë
212 D4 È
213 D5 i
214 D6 Í
215 D7 Î
216 D8 Ï
217 D9
218 DA
219 DB
220 DC
221 DD
222 DE
223 DF
224 E0 Ó
225 E1 ß
226 E2 Ô
227 E3 Ò
228 E4 õ
229 E5 Õ
230 E6 é

3
231 E7 þ
232 E8 Þ
233 E9 Ú
234 EA Û
235 EB Ù
236 EC ý
237 DE Ý
238 EE ¯
239 FF ´
240 F0
231 F1 ±
232 F2
243 F3 ¾
244 F4
245 F5 §
246 F6 ÷
247 F7 ¸
248 F8 °
249 F9 ¨
250 FA ·
241 FB ¹
242 FC ³
253 FD ²
254 FE
255 FF

Hay algunos símbolos que varían de acuerdo al monitor.

De ésta forma también se pueden almacenar cadenas de símbolos alfanuméricos


como los de este texto en forma de números. De hecho, este archivo está codificado en
código ASCII. Al final de cada línea hay un Car Return (Regreso de Carro) invisible y al
final del archivo hay un End of Text (Fin de Texto) invisible también. Lo único que se
necesita es ser consistente en la interpretación de la información que contiene un archivo.
Si ese archivo contiene caracteres alfanuméricos esté se debe recuperar utilizando la
tabla de código ASCII y si el archivo contiene números estos se deben recuperar
utilizando los procedimientos para recuperar números.

Existe un cuarto tipo de dato básico. En algunos lenguajes no aparece


explícitamente como en el lenguaje C aunque se puede implementar con variables
enteras que toman sólo dos valores 1 y 0 y son llamadas comúnmente banderas. Este
tipo de dato es el tipo de dato booleano, al cual se le da este nombre ya que viene de la
lógica de Boole y que solo puede tomar dos valores, o "falso" o "verdadero" y
generalmente se utiliza un byte para almacenarlo aunque en realidad sólo se necesita un
bit.

De está forma es como se pueden representar y almacenar en la computadora los


cuatro tipos de datos básicos, enteros, reales, caracter y booleanos.

3
EJERCICIOS CAPÍTULO 3 Fecha de entrega: ______________
Nombre (comenzando por el apellido): ________________________________________
La calificación se calcula sobre el número total de respuestas, en este caso, 30.
1.- ¿Qué intervalo de números se puede representar con ocho bits y en donde uno es
para el signo? ____________________________________________________________
2.- ¿Qué intervalo de números se puede representar dieciseis bits y en donde un bit es
para el signo? ____________________________________________________________
3.- ¿Cuántas cifras significativas se logran con una mantisa de cinco bits y en donde un
bit es para el signo? _______________________________________________________
4.- ¿Cuántas cifras significativas se logran con una mantisa deocho bits y en conde un bit
es para el signo? _________________________________________________________
5.- ¿Cuántas cifras significativas se logran con una mantisa de dos bytes en donde un bit
es el signo? _____________________________________________________________
6.- ¿Cuántas cifras significativas se logran con una mantisa de cuatro bytes en donde un
bit es para signo? ________________________________________________________
7.- ¿Cuántas cifras significativas se logran con una mantisa de 42 bits en donde un bit es
para el signo? ____________________________________________________________
8.- Escriba el número en decimal con signo al que corresponden los siguientes números:
010100112 001111012 010011102 010101012 011111112
________10 ________10 ________10 ________10 _________10
9.- Escriba su complemento a 1(1’):
________ ________ ________ _________ _________
10.- Escriba su complemento a 2 (2’):
_________ _________ _______ ________ _________
11.- Escriba el correspondiente en decimal con signo de los números anteriores en
representación 2’ con signo:
________10 _______10 ________10 ________10 ________10
12.- ¿Qué pasa si se le saca el complemento a 2 dos veces a un número? ____________
_______________________________________________________________________
_______________________________________________________________________

3
13.- Escribir la cadena "hola mundo" en código ASCII en hexadecimal:

14.- Escriba la cadena de su nombre de pila en código ASCII en hexadecimal:

3
4.- DESCRIPCIÓN DE UNA COMPUTADORA

Es posible hacer la descripción de una computadora desde dos puntos de vista, el


punto de vista físico y el punto de vista lógico.

DESCRIPCIÓN FÍSICA

Desde el punto de vista físico una computadora está formada básicamente de tres
partes:

a) El procesador
b) La memoria
c) Puertos de Entrada/Salida

Estas tres partes interactúan como una pequeña ciudad en donde la memoria
funciona como un almacén de datos, el procesador toma datos de la memoria, los
procesa y regresa los resultados y finalmente los puertos de entrada/salida (input/output)
a través de los cuales la información entra y sale de la computadora.

Para que los datos puedan viajar dentro de la ciudad es necesario crear autopistas
para que los datos viajen. Esta autopista para los datos se conoce como canal de datos
(Data Bus) donde los datos se suben para viajar a través de él.

Para saber a que dirección se requiere acceder se utiliza un canal llamado canal
de direcciones (Address Bus) a través del cual el microprocesador direcciona el registro
que desea acceder.

Para que los datos sean aportados a los canales se utilizan una serie de líneas de
control que le indican a los diferentes componentes cuando deben aportar su dato al
canal, y a los que lo van a recibir, cuando deben hacer la captura del dato. Las dos líneas
más importantes de este canal son habilita salida (Output Enable o OE) y habilita captura
(Latch Enable o LE) las cuales llegan a la mayoría de los componentes. Estas líneas
salen de la Unidad de Control, la cual está dentro del procesador

Dentro del procesador se encuentran los registros auxiliares, los cuales sirven
como almacenamiento temporal de la información. Además de registros, dentro del
procesador se encuentra una Unidad Aritmética Lógica (Arinmetic Logic Unit o ALU) a
través de la cual el procesador es capaz de realizar operaciones aritméticas tales como
sumas y restas, y lógicas tales como “and”, “or”, “not” entre los bits de los los registros.

El único lenguaje que reconoce el procesador es el código de máquina, el cual


consiste en un código asignado a cada operación seguido opcionalmente de operandos.
Cada código tiene su correspondiente mnemónico el cual es un nombre con letras que
sirve para manejar la operación en una forma más práctica. Ejemplos de mnemónicos
son las operaciones ADD que suma el acumulador con otro registro y el operador SUB
que realiza la resta. Normalmente todo procesador tiene un registro Acumulador el cual

3
normalmente sirve como fuente y destino de las operaciones aritméticas y lógicas.
Después de ejecutar la operación, el resultado, el cual queda en el acumulador, se envía
a memoria.

Es posible programar en lenguaje ensamblador, es decir con mnemónicos, y


después convertirlo a código de máquina con un programa llamado macroensamblador
(macroassembler) pero esto implica la dificultad de hacer programas muy difíciles de
comprender y de verificar, aunque ciertas secciones de los sistemas operativos es
necesario programarlas en ensamblador o para los segmentos de código en los que
traducen las instrucciones de alto nivel los programadores primero las programan en
ensamblador, de hecho, cada que se fabrica un procesador también se tiene que elaborar
su macroensamblador. En lugar de ésto, se utilizan lenguajes de programación de alto
nivel donde se puede programar a un mayor nivel conceptual sin preocuparse del manejo
interno de memoria y de los registros. El manejo de memoria quedará a cargo del
manejador de memoria del sistema operativo, de tal manera que al programar en un
lenguaje de alto nivel no es necesario saber que espacios de memoria ya están
asignados, cuales no y donde se encuentran. El sistema operativo se hará cargo de la
administración de la memoria durante todo el tiempo, incluso cuando estemos corriendo
un programa.

El manejar lenguaje de alto nivel también hace posible manejos repetitivos de


secuencias de código prefabricado de tal manera que para un tipo de instrucción de alto
nivel habrá una secuencia de código de máquina que cada vez que se utilice esa
instrucción lo único que se hará es agregar ese segmento de código al programa.
Ejemplos de estos códigos son el código de las instrucciones Read y Write.

De esta manera, es posible programar en un lenguaje de alto nivel y traducirlo a


código de máquina. El código que se genera en un lenguaje de alto nivel se conoce como
código fuente. Un compilador es un programa que traduce el código fuente a código de
máquina. En realidad lo único que hace un compilador es reconocer si la secuencia de
código fuente pertenece al lenguaje generado por una gramática dada, pero de paso se
genera el código de máquina o ejecutable. Cuando se tienen programas muy grandes
estos se compilan por modulos. El resultado de la compilación de estos modulos es
codigo objeto. El código objeto es un código que ya está compilado pero no está ligado
con los otros segmentos. Cuando se compila un programa que invoca procedimientos de
librerías se liga el código de los módulos con el del programa principal produciendo
finalmente el código ejecutable.

Entonces, el proceso para la elaboración de un programa es editar el código fuente


en un lenguaje de alto nivel, compilarlo y obtener el código ejecutable. Para obtener
código ejecutable es necesario ligar (link) los segmentos de código objeto que se
generaron, esto lo hacen automáticamente las herramientas de programación después de
que el programa ya no tiene errores sintácticos.

El lector se podrá preguntar ¿Y qué pasa con el teclado, el monitor y las unidades
de disco? Todas estas son accedidas a través de puertos. Internamente para la
computadora es lo mismo un monitor que una impresora, ya que las dos son salidas, lo

3
único que varía son los programas que controlan las diferentes salidas de la
computadora.

Ya que la transferencia de información puerto-memoria es muy lenta puesto que


los datos tienen que pasar forzosamente por el procesador, se ideó un sistema llamado
de Acceso Directo a Memoria (Direct Memory Address o DMA) el cual puede hacerse
cargo momentáneamente de los canales pasando directamente los datos de los puertos a
la memoria y viceversa. Éste DMA está bajo el control del procesador y cuando está
transfiriendo datos, el procesador no puede hacer uso de los canales. El DMA no es
utilizado en arquitecturas en donde los puertos están mapeados en memoria como es el
caso de las PC's.

Se ha dado en llamar CPU (Central Processing Unit o CPU) a la caja que contiene
la tarjeta madre (Mother Board) y las unidades de disco, pero en realidad el CPU está
adentro y es únicamente el procesador o actualmente llamado microprocesador ya que
está en una sola pastilla de silicio.

El procesador siempre está ejecutando instrucciones. Una de las formas de desviar


el flujo de ejecución es a través de las interrupciones. Cada vez que un dispositivo
periférico transmite un dato al puerto de entrada, éste activa a un circuito integrado
llamado controlador de interrupciones el cual interrumpe a su vez al CPU para que salte
a la dirección de servicio de la interrupción que acaba de sucitarse. De esta manera el
procesador no tiene que estar revisando todo el tiempo si ya hay un dato nuevo en cada
registro de un puerto de entrada.

En cuanto a transmisión de datos, hay dos formas en que la computadora puede


enviar y recibir datos. Una forma es en paralelo, byte por byte, la cual se usa para
distancias cortas y es de alta velocidad (normalmente usada para las impresoras) y en
serie, en donde se envía bit por bit y la cual se utiliza para transmisión a grandes
distancias, con la ventaja de que es más barata ya que requiere menos hilos pero con la
desventaja de que es más lenta (utilizada para conectarse en red o a un servidor remoto
a través de un módem por vía telefónica).

Con el mismo esquema una computadora puede ser monousuario o multiusuario,


con la única diferencia de que en un sistema multiusuario debe de contar con un sistema
operativo multiusuario que pueda dar servicio a varios usuarios compartiendo la memoria,
el CPU y los recursos y por supuesto estar conectada a una red. Ejemplos de sistemas
operativos multiusuario son Unix y Linux. Un sistema operativo multiusuario se define
como un administrador de los recursos del sistema que tiene el objeto de darle servicio a
los diferentes usuarios del sistema.

Con el modelo cliente-servidor en el cual se instalan todos los programas en un


servidor y los clientes pueden hacer uso remoto de los programas. Actualmente se
utilizan computadoras muy poderosas como servidores y generalmente a estás se les
instala una versión de Linux aunque Microsof también tiene su Windows Server. Ejemplos
de servidores son los servidores de páginas webs.

3
DESCRIPCIÓN LÓGICA

En cuanto a la descripción lógica, una computadora es un modelo de modelos. La


idea matemática en la cual se basa la idea de la computadora es hacer un modelo donde
se pudieran representar aspectos de la realidad.

El área de las matemáticas que sustenta la parte teórica de la computación es la


llamada teoría matemática de la computación. En ésta se trabajan conceptos como
autómata, autómata finito, gramáticas y la famosa máquina de Turing.

Básicamente a través de autómatas es posible hacer máquinas que reconozcan


cadenas. Un autómata es una máquina constituida por un conjunto de estados en el cual
un estado es de inicio y uno o varios estados finales y donde a través de entradas va
pasando por los diferentes estados generando simultáneamente salidas, se caracteriza
por hacer procesos cíclicos. De aquí se deriva la palabra automático, es decir, que trabaja
por medio de autómatas. Estas cadenas están constituidas por símbolos. Para generar
una cadena es necesario aplicar las reglas de producción de tal forma que al
establecerse reglas de producción se establecen simultáneamente un conjunto infinito de
cadenas que se pueden formar, pero estas cadenas son especiales, pertenecen a una
gramática.

Por lo tanto, una gramática formal está constituida por un conjunto de reglas de
producción, son esquemas generativos, modelos dinámicos para generar frases de un
lenguaje.

Las reglas de producción son como su nombre lo indica reglas que se aplican para
generar cadenas pertenecientes al lenguaje.

Ejemplo de una gramática:

G = ( {S}, {0,1}, P, S)

Donde el primer conjunto denota el vocabulario no terminal (Vn), el segundo


conjunto denota el vocabulario terminal (Vt), P denota el conjunto de reglas de producción
y S el símbolo especial de inicio.

En donde P consta de las siguientes reglas:

1.- S  0S1
2.- S  01

Se puede aplicar inicialmente la regla 1 o bien la 2, por que ambas contienen a S


como miembro izquierdo.

Si se aplica la regla 2 se obtiene:

3
S  01 (la doble flecha representa la aplicación de alguna regla)

y el proceso terminaría allí, ya que la cadena 01 contiene únicamente elementos


terminales.

Si se aplicará inicialmente la regla 1, sin embargo, se obtendría lo siguiente:

S  0S1

y como el lado derecho de esta aplicación contiene al menos un elemento no


terminal, se vuelve a aplicar la regla ( la 2), para obtener

0S1  0011

que ya es una cadena terminal y por lo tanto pertenece al lenguaje que produce
esta gramática.

Así, las reglas de producción son, como su nombre lo indican, reglas que al
aplicarlas producen cadenas con símbolos terminales y no terminales. Las cadenas que
constan únicamente de símbolos terminales constituyen las cadenas que forman el
lenguaje. Un símbolo es terminal cuando ya no se puede aplicar sobre él ninguna regla
de producción, ejemplo "0" o "1". Ejemplo de no terminal "S".

Al elaborar un programa nosotros producimos una cadena, el compilador se


encarga de verificar si aplicando las reglas de producción se puede reconocer esta
cadena. Si esto sucede, se comprueba que esta cadena pertenece al lenguaje generado
por la gramática y de paso se genera el código objeto o ejecutable.

Los autómatas se clasifican a través de la teoría matemática de la computación en


cuatro y corresponden a un tipo de gramática que pueden reconocer.

Reconocedor Gramática
Máquina de Turing Tipo 0
Autómata Lineal Tipo 1 (Sensible al contexto)
Autómata de Pila Tipo 2 (Independiente del contexto)
Autómata Finito Tipo 3 (Regular)

Los compiladores son autómatas de pila, lo que quiere decir que reconocen
lenguajes generados por gramáticas de tipo 2, independientes del contexto.

La computadora es una herramienta que nos permite hacer representaciones de


aspectos de realidad. Por lo tanto, lo que aprenderemos a hacer aquí es a hacer
representaciones con los recursos con los que se cuenten. En un principio los primeros
recursos son 1’s y 0’ y con ellos se construirán objetos más complejos.

3
El término computabilidad proviene de computo. En los despachos de contabilidad
había trabajadoras especializadas que su único trabajo era realizar cómputos, es decir
operaciones aritméticas. Turing tomó de estas el término computable ya que la máquina
que el ideó era capaz de realizar el mismo trabajo que una de estas secretarias. Una
secretaria solo necesita papel y lápiz para realizar sus cómputos, de la misma manera la
máquina de Turíng solo necesita una cinta infinita y una cabeza lectora-escritora para
hacer sus cómputos. La máquina de Turing se puede programar mediante una tabla de
estímulo-respuesta y de esta forma, una vez que se inicia el proceso, la máquina realiza
los cómputos indicados por su tabla de estímulo-respuesta. Por lo tanto, un problema es
computable cuando existe una máquina de Turing que se puede programar para resolver
el problema, es decir, cuando existe una descripción algorítmica para resolver el
problema.

Así pues, los datos se representan con 1’s y 0’s y los algoritmos son descripciones
de procesos sobre ciertos datos. Una representación es el ejercicio de representar una
cosa por otra, ejemplo un capacitor descargado puede representar un valor lógico “falso”
o un símbolo “0” y uno cargado puede representar un valor lógico “verdad” o un símbolo
“1” en un determinado proceso. Una descripción es un relato que cuenta como es cierto
objeto, proceso o hecho. Ejemplo: un escritor puede hacer una descripción de una tarde
soleada de primavera en algún lugar paradisiaco.

Un algoritmo también es una descripción de un proceso para resolver un problema


en términos computables sobre cierta representación de aspectos de la realidad como
podrían ser presión, volumen, temperatura, flujo, etc. Por lo tanto programar es el
ejercicio de describir un proceso sobre cierta representación de ciertos los aspectos de la
realidad.

3
EJERCICIOS CAPÍTULO 4 Fecha de entrega: ______________
Nombre (comenzando por el apellido): ________________________________________
1.- Desde el punto de vista físico ¿Cuáles son las tres partes más importantes de que
consta una computadora y qué funciones tienen? ________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
2.- ¿Qué función tiene el canal de datos? ______________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
3.- ¿Qué función tiene el canal de direcciones? _________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
4.- ¿Qué función tienen las líneas de control? ___________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
5.- ¿Para qué sirve la Unidad Aritmética/Lógica? ________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
6.- ¿Para que sirve el DMA? ________________________________________________

3
_______________________________________________________________________
_______________________________________________________________________
7.- ¿Qué es el código de máquina? ___________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
8.- ¿Qué son las interrupciones? _____________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
9.- ¿Cuáles son las dos formas de transmitir datos de una computadora? _____________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
10.- ¿Desde el punto de vista lógico cual es la idea en la que se basa la creación de la
computadora?____________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
11.- ¿Qué es un autómata? _________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
12.- ¿Qué es una gramática? ________________________________________________
_______________________________________________________________________
_______________________________________________________________________

3
_______________________________________________________________________
_______________________________________________________________________
13.- ¿Qué son las reglas de producción? ______________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
14.- ¿Qué es un compilador? ________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
15.- ¿Qué es programar? ___________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
16.- ¿Que significa que un proceso sea computable? _____________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
______________________________________________________________________
17.- ¿Qué es una descripción y de un ejemplo? _________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
18.- ¿Qué es una representación y de un ejemplo? ______________________________
_______________________________________________________________________
_______________________________________________________________________

3
_______________________________________________________________________
_______________________________________________________________________

3
5.- MÉTODO DE CASCADA

La elaboración de programas no es un proceso empírico, existe un método para la


su creación. A través del tiempo la forma en que se han construido ha ido evolucionando.
El primer método que se ideó para elaborarlos es el llamado método de cascada.

El método de cascada está formado por seis etapas, en donde una vez completada
cada etapa, se va pasando a la siguiente no existiendo la posibilidad del regresar, de ahí
el nombre del método.

Las etapas del método de cascada son las siguientes:

1) Comprensión del problema


2) Análisis del problema
3) Programación del modelo de la solución propuesta en pseudocódigo
4) Codificación en un lenguaje formal
5) Carga en la computadora para su ejecución, prueba y ajuste
6) Mantenimiento durante su tiempo de vida útil

1.- COMPRENSIÓN DEL PROBLEMA.

En programación es sumamente importante comprender el problema antes de


comenzar a elaborar su solución. Por lo tanto primero hay que familiarizarse con el
problema e inclusive hacer algunos ejemplos para corroborar que ya se ha comprendido
bien el problema que se requiere solucionar. La razón de este punto es que en ocasiones
los programadores comenzaban a trabajar en la solución sin tener la certeza de haber
comprendido bien el problema y cuando entregaban la solución al cliente, éste
encontraba que los Ingenieros de Software no habían comprendido bien sus
requerimientos y por lo tanto la solución presentada no satisfacía sus expectativas
generando fuertes conflictos mercantiles. Por lo tanto, antes de comenzar a trabajar en la
solución de un problema se debe tener la certeza de que se ha comprendido
perfectamente el problema, inclusive haciendo manualmente algunos ejemplos.

En este paso se hace la descripción del problema en lenguaje natural. El lenguaje


natural puede ser cualquier lenguaje humano, en nuestro caso será el Español. Ésta
descripción puede servir como el encabezado del problema cuando se comience a cargar
el programa. A esta descripción se le llama también especificación del problema en
Ingeniería de Software y es la descripción del ¿qué?, el ¿qué vamos a resolver?

2.- ANÁLISIS DEL PROBLEMA

El significado etimológico de la palabra análisis es descomposición. En este paso


se analiza el problema, se descompone y se medita en el algoritmo de solución, se
plantean las variables y las estructuras de datos que se van a requerir y la forma en que
se va a representar la información en la computadora. Un algoritmo es un procedimiento
aplicado sobre ciertos datos para obtener un resultado final.

3
El algoritmo solución puede ser expresado en lenguaje natural y además se puede
hacer en forma de especificación, como si fuera una receta de cocina. Algunos problemas
matemáticos ya tienen un algoritmo solución por lo que no hay necesidad de buscarlo. En
ocasiones la solución está expresada en lenguaje matemático y en otras lo podemos
conceptualizar en la mente aunque es recomendable transcribirlo en lenguaje natural.

Un algoritmo es un procedimiento computacional bien definido que toma algún


valor o conjunto de valores como entrada y produce algún valor o conjunto de valores
como salida. Es un conjunto de secuencias de pasos computacionales que transforman
una entrada en una salida. Es también una herramienta para resolver un problema
computacional bien especificado.

Un algoritmo debe tener las siguientes cuatro propiedades:

1. Finitud: debe acabar en un número finito de pasos.


2. Definibilidad: debe definirse en forma precisa y libre de ambigüedad.
3. Correctez: debe de resolver perfectamente el problema para el que fue
diseñado.
4. Eficiente: debe ocupar el menor número de recursos espacio/tiempo.

Uno de los algoritmos más antiguos conocidos es el algoritmo de Euclides el cual


encuentra el máximo común divisor de dos números enteros positivos a través de
divisiones sucesivas. El término algoritmo proviene del matemático Muhammad ibn Musa
al-Khwarizmi, que vivió aproximadamente entre los años 780 y 850 D.C. en la actual
nación Iraní. Él describió la realización de operaciones elementales en el sistema de
numeración decimal. Del nombre al-Khwarizimi se obtuvo la derivación de algoritmo.

Aquí tendríamos la segunda especificación y es la especificación del ¿cómo? en


lenguaje natural.

3.- PROGRAMACIÓN

En esta etapa se escribe la solución en pseudocódigo. El pseudocódigo es un


lenguaje neutro estructurado a través del cual es posible hacer descripciones de una
solución en términos computacionales. Con neutro queremos decir que no está casado
con ninguna herramienta de programación, es un lenguaje por derecho propio. En
muchas ocasiones se confunde con Pascal debido a que Niclaus Wirth construyó un
lenguaje formal basado en las estructuras de control del pseudocódigo, he aquí la razón
de la alta similitud entre Pascal y el pseudocódigo, aunque Pascal quedó más limitado
que el pseudocódigo en algunos casos como el del “case”. Es estructurado ya que el
control del flujo del programa se realiza mediante estructuras de control de flujo. Es
importante aclarar también que los detalles de sintaxis no serán tan exhaustivos en
pseudocódigo ya que este programa no se compilará, por lo que la sintaxis no será tan
rigurosa, aunque se debe de tratar de seguir lo más posible.

3
La sintaxis trata acerca de las reglas de construcción de los enunciados de un
lenguaje. Ejemplo: la sintaxis de la gramática del Español marca que una oración debe
estar constituida por las siguientes partes, sujeto, verbo y complemento. De la misma
forma, los enunciados en un programa deben de estar constituidos dados los siguientes
casos:

a) Si es un enunciado de asignación por una variable, seguido del signo de


asignación seguido de una expresión.
b) Si es un llamado a procedimiento por el nombre del procedimiento y los
argumentos del llamado.
c) Si es una estructura de control, dependiendo de la estructura, la
secuencia adecuada de palabras reservadas con las variables y
condiciones requeridas, ejemplo: para la estructura de control “if” en su
versión más simple la regla de construcción es la palabra reservada “if”
seguido de condición seguido de la palabra reservada “then” seguido de
enunciado.

En ocasiones las reglas de sintaxis se muestran en forma de diagramas. Cualquier


omisión o desorden en la secuencia causará un error de sintaxis.

Si el algoritmo ya existe, partiremos del algoritmo o de su descripción en lenguaje


natural transcribiéndolo en términos computacionales. Es importante mencionar que un
problema puede tener ya una solución algorítmica que no necesariamente esta se
encuentre descrita en términos computacionales. Aquí construiremos la tercera
especificación, plasmaremos el ¿cómo?, el ¿cómo se resuelve? pero esta vez en
términos computacionales en pseudocódigo. El pseudocódigo es un lenguaje
estructurado neutro y completo que sirve como vehículo descriptor y como modelo de la
representación de la solución. Estructurado ya que el control del flujo se lleva a cabo en
base a estructuras de control de flujo. Neutro ya que no está sujeto a ningún lenguaje de
programación y completo ya que con el se puede implementar cualquier algoritmo que se
requiera. Si el problema es muy complejo podemos usar el método de refinamientos
sucesivos a través del cual podemos hacer que poco a poco la descripción en lenguaje
natural se transforme en una descripción en términos computacionales de tal forma que al
final sea posible codificar sin ningún problema ésta descripción en algún lenguaje formal
como Pascal o C.

Pueden existir varias formas de solucionar un problema, además, cada solución


puede tener optimizaciones, por lo tanto el número de soluciones de un problema
computacional es infinito.

Para verificar si el algoritmo funciona correctamente se elaboran uno o varios


ejemplos de prueba y se verifica en papel que funcione bien antes de codificarlo. Éstos
ejemplos nos van a servir cuando vayamos a probar si nuestro programa funciona
adecuadamente. Es importante que se comience por ejemplos sencillos.

4.- CODIFICACIÓN

3
En esta etapa se procede a la codificación del programa en un lenguaje formal. Un
lenguaje formal es aquel generado por una gramática desde el punto de vista de la teoría
matemática de la computación. Es posible construir un reconocedor para cualquier
cadena que pertenezca a este lenguaje. A este reconocedor se le llama Compilador. Para
elaborar cadenas válidas de este lenguaje es necesario que el programador conozca
perfectamente las reglas de sintaxis del lenguaje que se va a utilizar como herramienta,
así como sus recursos y particularidades.

En este paso si es importante respetar con todo rigor las reglas de sintaxis ya que
de otra manera el programa o no se compilará correctamente o no realizará la tarea que
se desea que realice, además de que no debe de haber errores tipográficos. Un error
tipográfico es aquel en donde se escribe un carácter por otro, o se escribe doble o no se
escribió en una palabra, ejemplo: en lugar de escribir “if” escribir “iff”.

5.- CARGA

En esta etapa se procede a editar el programa con una herramienta de


programación, se eliminan los errores tipográficos, sintácticos y lógicos, se depura, se
prueba y se obtiene un programa ejecutable.

Deberemos probar que nuestro programa corra con los ejemplos hechos en la
etapa de programación para verificar que el algoritmo funciona como deseamos y
posteriormente con casos límite y con entradas absurdas para ver cómo se comporta en
éstos casos.

Es importante que la primera versión del programa sea una versión sencilla, sin
muchos adornos ya que el punto es que resuelva el problema. Más adelante se le pueden
poner adornos o mejorar la presentación con la seguridad de que el programa ya corre.
En muchas ocasiones los programadores se comen el tiempo poniendo adornos a sus
programas fallando en el tiempo de entrega. De nada servirán todos los adornos si el
programa no corre.

En computación se debe tener conciencia de que el tiempo es un recurso, por lo


que cada mejora al programa se debe de ponderar bajo un análisis de costo/beneficio
tomando siempre en cuenta los recursos en tiempo asignados al proyecto.

Se debe tener cuidado al poner los filtros y validación de entradas para que el
programa no deje de mostrar su objetivo más importante.

Los programas profesionales deben contener estos filtros y validaciones ya que


una política de Ingeniería de Software es hacer programas que no puedan ser "tirados"
por el usuario, se les llama "programas a prueba de tontos".

En esta etapa obtendremos las versión 1.0 de nuestra solución. Deberemos


guardar una copia en un lugar seguro ya que esto garantizará que tengamos algo que
entregar si las mejoras o las optimizaciones no quedarán a tiempo. Recordemos que lo
peor que le puede pasar a un programador es no tener nada que entregar.

3
6.- MANTENIMIENTO DEL SISTEMA

Esta etapa se realiza normalmente en los sistemas grandes ya que cuando entran
en operación es posible que durante su uso se detecten fallas o se promuevan mejoras,
por lo que debe de haber un equipo de personas que se encarguen de darle
mantenimiento al sistema. En el desarrollo de los sistemas grandes es necesario que
éstos queden bien documentados ya que en caso de requerir algún cambio toda la
información debe estar disponible. Todos los proyectos grandes llevan un registro donde
se almacena toda la información del sistema.

Nosotros no ejecutaremos esta etapa ya que únicamente desarrollaremos el


programa, lo utilizaremos por un tiempo corto y este quedará guardado en algún lugar, sin
embargo trataremos de hacer buenos programas que en caso de necesitarlos tiempo
después seamos capaces de comprender nuestro programa y poderle hacer
modificaciones. Una regla en Ingeniería de Software es hacer programas que cualquier
programador sea capaz de comprender y no programas encriptados que únicamente el
autor sabe como funcionan.

3
3
EJERCICIOS CAPÍTULO 5 Fecha de entrega: ______________
Nombre: ________________________________________________________________
1.- Describa el método de desarrollo de cascada y explique brevemente cada una de sus
etapas: _________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
2.- ¿Qué es un algoritmo? __________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
3.- ¿Qué es el pseudocódigo? _______________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
4.- ¿Qué es un lenguaje natural? _____________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
5.- ¿Qué es un lenguaje estructurado? ________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
6.- ¿Cuales son las reglas de sintaxis? ________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________

3
3
6.- ESTRUCTURA DE UN PROGRAMA, ENUNCIADOS, ENUNCIADOS DE
ASIGNACIÓN, PALABRAS RESERVADAS E IDENTIFICADORES
El programa que rige las actividades de todo el programa es llamado programa
principal. Este programa puede ser ayudado por otros subprogramas llamados módulos,
procedimientos o subrutinas.

La estructura general de un programa principal es la siguiente:

Nombre del programa

Declaraciones de variables

Cuerpo del programa

Las declaraciones de variables sirven, como su nombre lo dice, para declarar las
variables que se van a utilizar en el programa. No es posible utilizar una variable que no
se haya declarado antes.

Ejemplo de declaraciones de variables:

A, B, C: entero;
D, E, GradosFahrenheit: real;
H: char;
Nombre: cadena[10];

El cuerpo del programa estará formado por enunciados. Un enunciado es una


cadena de símbolos que el compilador puede reconocer como cadena perteneciente al
lenguaje de su gramática. Normalmente la computadora ejecuta los enunciados
secuencialmente pero en ocasiones es necesario ejecutar secuencias de código
repetitivamente o saltar a otros enunciados. Las estructuras de control de flujo se utilizan
para dirigir el flujo de ejecución de un programa. La primera estructura de control de flujo
que utilizaremos es la secuenciación.

El ejemplo más sencillo de enunciado es el enunciado de asignación. Un


enunciado de asignación es aquel en donde se evalúa una expresión y se asigna a la
variable que está a la izquierda del signo de asignación. Éste enunciado se construye con
el nombre de una variable, el signo de la asignación y una expresión. Una expresión es
una secuencia de caracteres que indican una constante, una variable o una función o un
conjunto de todas ellas concatenadas con un conjunto de operadores junto con un
conjunto de paréntesis. Ejemplo:

0.5 - A + B * C / (D * Seno(X)) - 2

3
Una constante es una cadena de caracteres numéricos que representan una
cantidad. Ejemplo:
4, 0.5, -3.2

Una función es un código predefinido que calcula un valor a través de uno o varios
argumentos y se sustituye en su invocación. En todos los lenguajes existen un conjunto
de funciones predefinidas o bibliotecas de funciones predefinidas. Ejemplos:

Seno(X), Coseno(Y), Exponencial(Z)

Como es necesario hacer explicita la operación de multiplicación y no existe el


símbolo “•” en los teclados se optó por representarlo por un asterisco y el operador
división con el símbolo “/”.

Escribiremos el programa primero en un lenguaje llamado pseudocódigo. El


pseudocódigo es un lenguaje neutro que no está asociado a ningún lenguaje de
programación formal, sirve para realizar especificaciones de algoritmos y programas,
aunque tiene su propia sintaxis. Un algoritmo es un procedimiento que consta de una
serie de pasos no ambiguos que se pueden ejecutar en un tiempo finito. Las reglas de
sintaxis son las reglas de construcción estructurales de un lenguaje. Ejemplo: En el
lenguaje Español una oración debe de formarse con una categoría sujeto seguida de un
verbo y seguida de un complemento. Se llaman categorías ya que un conjunto de
palabras o frases pertenecen a una categoría.

En pseudocódigo el símbolo de asignación se escribe con una flecha apuntando a


la izquierda.

Ejemplos de enunciados de asignación en pseudocódigo:

A←5

A←B

A ← Seno (1.0)

A ← 5 + B * Seno (1.0)

En los lenguajes estructurados el formato es libre, es decir, se puede escribir en


cualquier columna a diferencia de Fortran en donde se tenía que comenzar a escribir el
enunciado en una columna determinada. En pseudocódigo el “;” se utiliza para separar
enunciados que se encuentran en el mismo renglón, en Pascal “;” se utiliza para separar
enunciados y en C se utiliza al final de cada enunciado.

En los lenguajes de programación la asignación se implementa con un símbolo o


conjunto de símbolos, por ejemplo en Pascal se implementa con los caracteres ":=" y en
el lenguaje C con un simple "=" y son distintos al operador de comparación que en Pascal
se implementa con "=" y en C con "==" como veremos más adelante.

3
Ya que el orden en la ejecución de los operadores en una expresión genera
resultados distintos es necesario tener un orden de precedencia de operadores para no
tener ambigüedad en la evaluación. El orden de precedencia es el criterio para resolver el
orden de evaluación en una expresión.
Ejemplo:

Las expresiones:

A←B+D*C

A ← (B + C ) * D

no producirán el mismo resultado ya que sin paréntesis la expresión se resolverá


evaluando primero el operador "*" y luego el operador "+". Si se escribe esta expresión
pensando en que primero se evaluará el operador + y luego el * se tendrá un resultado
erróneo y el error podrá quedar oculto ya que la expresión es sintácticamente correcta y
el compilador no marcará ningún error.

Para evitar este tipo de errores es recomendable dividir la expresión en


subexpresiones y asignar temporalmente los resultados parciales a variables temporales.
Una vez que el programa este corriendo adecuadamente integrar estas variables
temporales a la expresión original hasta que no quede ninguna variable temporal. Esto
expondrá el error en caso de existir alguno.

Para saber en qué orden se evaluarán los operadores es necesario consultar la


tabla de precedencia de operadores de cada lenguaje. El orden de precedencia va de
arriba hacia abajo y cuando hay varios en el mismo nivel es de izquierda a derecha. Los
operadores unarios son aquellos que aplican sobre un operando, ejemplo: –A. Los
operadores unarios se evalúan antes que los binarios. Los operadores binarios de aplican
sobre dos operandos, ejemplo: A + B.

Tabla de Precedencia para Pascal


paréntesis
Evaluación de funciones
– unario
*, /, div y mod
+, - binario

Pascal es un lenguaje fuertemente tipeado lo que quiere decir que el programador


debe de tener cuidado de no asignar un resultado que no corresponda al tipo de variable.
Si se le asigna a una variable un dato que no sea del mismo tipo del que es ella el

3
compilador marcará un error, por lo tanto, es importante que el programador verifique que
el dato que se le va a asignar a una variable sea del mismo tipo de la variable, ejemplo:

C := A / B;

La operación A / B produce un resultado real, por lo que C debe ser de tipo real, si
no se hace de esta manera el compilador marcará un error.

En Pascal el operador div entrega como resultado un entero, es decir, trunca el


resultado de la división, a diferencia del operador "/" que entrega como resultado un real
por lo cual la variable a la que se le asigna el resultado del operador div debe de ser
entera, mientras que el tipo de dato de la variable a la que se le asignaría el resultado de
un operador "/" tendría que ser real, de otra manera el compilador marcará un error.
Utilizar el operador div es equivalente a hacer una división en C y después utilizar la
función trunk la cual trunca la parte fraccionaria. El operador mod calcula el módulo o
residuo de la división entre dos operandos. Ejemplo: A := 17 mod 3 entregará como
resultado 2.

Por ejemplo expresión se evalúa de la siguiente manera:

A ← B + C * D - E div F / G
\____/
T1
\_____/
T2
\______/
T3
\______/
T4
\_____________/
A

En la siguiente expresión los paréntesis son los que tienen la mayor precedencia
por lo que las expresiones que se encuentren entre paréntesis se evalúan primero,
ejemplo:

D ← A * (B + C)
\_____/
T1
\_______/
D

En el lenguaje de programación C el tipo de dato real se declara como float, es


decir, flotante. Si se dividen dos enteros el resultado producirá un entero por lo que si se
requiere que el resultado de la división de un float es necesario escribir una de las
constantes en formato flotante, esto se hace agregándole una parte decimal al número,
ejemplo:

3
c = 5 * (f – 32)/9

dará un resultado entero, pero la expresión:

c = 5.0 * (f – 32)/9

dará un resultado flotante.

Otro tipo de enunciado es el llamado a procedimiento. Un llamado a procedimiento


es, como su nombre lo indica, un llamado a un código de un procedimiento que ya fue
definido y compilado anteriormente. El llamado puede llevar argumentos. Los argumentos
son variables o constantes a través de las cuales el procedimiento que invoca envía datos
al procedimiento invocado. El procedimiento invocado puede regresar resultados en
alguna de estas variables. Ejemplo de llamado a procedimiento:

Lee (X) y Escribe (Y)

En el caso de Pascal, hay una lista de procedimientos y funciones incluidos en el


lenguaje. A estos procedimientos y funciones se les da el nombre de procedimientos y
funciones estandar. En el caso de Pascal Read, Write, ReadLn y WriteLn son
procedimientos estándar para los que no es necesario incluir ninguna librería. Puede
consultar su sintaxis posicionando el cursor debajo del nombre del procedimiento editado
y presionando las teclas Ctrl y F1 simultáneamente.

De tal forma que un programa en pseudocódigo queda de la siguiente forma:

programa Suma

A, B, C: entero

comienza
Lee(A)
Lee(B)
C=A+B
Escribe(C)
termina

Un programa en Pascal queda de la siguiente forma:

program Suma;

var
A, B, C: integer;

begin

3
ReadLn(A);
ReadLn(B);
C := A + B;
WriteLn(C)
end.

En cuanto al lenguaje de programación “C” el kernel o núcleo no incluye ninguna


función por lo que para utilizar cualquier función predefinida es necesario hacer la
inclusión de la biblioteca (o librería) en la que se encuentra, es decir, no cuenta con
funciones estandar. En C es necesario incluir la librería “stdio.h” (standar input output, la h
significa header) para utilizar los procedimientos scanf y printf. El procedimiento scanf
sirve para leer variables del teclado y el procedimiento printf sirve para desplegar
variables en la pantalla.

Un programa en C queda de la siguiente manera:

#include <stdio.h>
main()
{
int a, b, c;

scanf(“%d”, &a);
scanf(“%d”, &b);
c = a + b;
printf(“%d”, c);
}

La primera línea incluye la librería stdio.h en donde se encuentran definidas las


funciones scanf y printf. Note que en C son funciones y no procedimientos ya que en C
solo existen funciones (aunque funcionen también como procedimientos). Las llaves “{“y
”}” representan los metaparéntesis comienza y termina. Note que en C la declaración de
variables se hace dentro del cuerpo del programa.

En cuanto a la función scanf lo que está entre comillas dobles en el paréntesis es


el formato de impresión. El “%” es un caracter de escape para indicar que a continuación
viene el tipo de la variable que se va a leer o escribir, en este caso, la “d” que es para
indicar que el dato que se va a leer es un entero y el símbolo “&” (se lee “ampersand”) es
un operador que extrae la dirección de la variable (esto se verá más adelante) y
finalmente la variable que se va a leer o escribir. Note que en el caso del printf no se
requiere utilizar el operador “&” ya que el procedimiento no requiere la dirección de la
variable sino únicamente su nombre, esto se aclarará más adelante.

Tanto en Pascal como en C es posible desplegar una lista de variables con


caracteres alfanuméricos mezclados con una sola instrucción, esto se hace poniendo la
lista de variables y las cadenas intermedias separadas por comas en Pascal o comillas en
C, ejemplo:

3
WriteLn(‘El valor de ‘, Celsius:12:2’, ‘grados Celsius corresponde a ‘,
Fahrenheit:12:2, ‘ grados fahrenheit’);

El 10 indica que se escribirá en un campo de diez caracteres con cuatro decimales.

En C esto sería:

printf(“El valor de %12.2f grados Centígrados corresponde a %12.2f grados


Fahrenheit\n”, celcius, fahrenheit);

La cadena “\n” indica que se hará un salto de línea después de haber desplegado
la línea.

3
Para ayudar al estudiante se han incluido las tablas del orden de precedencia de
operadores de C y las tablas de descripción de las funciones scanf y printf.

Operadores Asociatividad
( ) [ ] -> Izquierda a derecha
! - ++ -- + - * & (tipo) sizeof Derecha a izquierda
* / % Izquierda a derecha
+- Izquierda a derecha
<< >> Izquierda a derecha
< <= > >= Izquierda a derecha
== != Izquierda a derecha
& Izquierda a derecha
^ Izquierda a derecha
| Izquierda a derecha
&& Izquierda a derecha
|| Izquierda a derecha
?: Derecha a izquierda
= += -= *= /= %= &= ^= |= <<= >>= Derecha a izquierda
, Izquierda a derecha

Tabla de precedencia y asociatividad de operadores de C

3
Carácter Dato de entrada; tipo de argumento
D entero decimal; int *.
I entero; int *. El entero puede estar en octal (iniciando con 0) o
hexadecimal (iniciando con 0x o 0X).
O entero octal (con o sin cero al principio); int *.
U entero decimal sin signo; unsigned int *.
X,x entero exadecimal (con o sin 0x o 0X al principio); int *.
C caracteres; char *. Los siguientes caracteres de entrada se podrán en el
arreglo indicado, hasta el número dado por el ancho de campo; el valor
por omisión es 1. No se agrega ‘\0’. En este caso se suprime el salto
normal sobre los caracteres de espacio en blando; para leer el siguiente
carácter que no sea blanco, use %ls.
S cadena de caracteres que no es espacio en blanco (no
entrecomillados);char *, apunta a un arreglo de caracteres
suficientemente grande para contener la cadena y un ‘\0’ terminal que se
agregará.
e,f,g número de punto flotante; float *. El formato de entrada para los float es
un signo optativo, una cadena de números posiblemente con un punto
decimal, y un campo optativo de exponente con una E o e seguida
posiblemente de un entero con signo.
P valor apuntador como se imprime por printf(“%p”); void *.
N escribe en el argumento el número de caracteres escritos hasta el
momento por esta llamada; int *. No se lee entrada alguna. La cuenta de
elementos convertidos no se incrementa.
[...] coincide con la mayor cadena no vacía de caracteres de entrada del
conjunto entre corchetes ; char *. Se agrega un ‘\0’. [ ] ...] incluye en el
conjunto.
[ˆ...] coincide con la mayor cadena no vacía de caracteres de entrada que no
sean del conjunto entre corchetes; char *. Se agrega un ‘\0’. [ˆ]...] incluye ]
en el conjunto
% literal; no se hace ninguna asignación.

Tabla de conversiones scanf

3
Carácter Tipo de argumento; Convertido a
d, I int; notación decimal con signo
O int; notación octal sin signo (sin ceros al principio
X,x int; notación hexadecimal sin signo (sin 0x o 0X al principio), utilizando
abcdef para 0x o ABCDF para 0X.
U int; notación decimal sin signo.
C int; carácter sencillo, después de la conversión a unsigned char.
S char *s; los caracteres de la cadena son impresos hasta que se alcanza
un ‘\0’ o hasta que ha sido impreso el número de caracteres indicados por
la presición.
F double; notación decimal de la forma [-][Link], en donde el número de
d es especificado por la precisión. La precisión por omisión es 6; una
precisión 0 suprime el punto decimal.
E,e double; notación decimal de la formma [-][Link]±xx o [-
][Link]±xx, en donde el número de d está especificado por la
precisión. La precisión por omisión es 6; una precisión 0 suprime el punto
decimal.
G,g double; usa %e o %E si el exponente es menor que –4 o mayor o igual
que la precisión; de otra forma es usado %f. Los ceros y el punto decimal
al finar no son impresos.
P void *; imprime como un apuntador (representación dependiente de la
implantación).
N int *; en número de caracteres escritos hasta el momento por esta
llamada a printf es escrito en el argumento. No es convertido ningún
argumento.
% No es convertido ningún argumento; se imprime como %.

Tabla de conversiones de printf

3
Secuencia de escape Acción
\a Character de alarma (campana)
\b Retroceso
\f Avance de hoja
\n Nueva línea
\r Regreso de carro
\t Tabulador horizontal
\v Tabulador vertical
\\ Diagonal invertida
\? Interrogación
\’ Apóstrofo
\” Comillas
\ooo Número octal
\xhh Número hexadecimal

Tabla de secuencias de escape del formato de impresión de printf

Las palabras enunciado y sentencia se manejarán como sinónimos.

El flujo de ejecución de los enunciados será controlado por las estructuras de


control de flujo. Más adelante se verán estas estructuras, por lo pronto es suficiente decir
que las estructuras de control de flujo controlan el flujo de la ejecución de un programa
haciendo que cierta secuencia se ejecute o no bajo ciertas condiciones o que se ejecute
un número de veces previamente establecido o hasta que se cumpla alguna condición de
paro o mientras una condición sea verdadera. Hasta este momento únicamente hemos
utilizado la primera estructura de control de flujo, la secuenciación, en la cual el orden en
la que se ejecutan los enunciados del programa es en secuencia, es decir uno después
de otro.

Si el programa requiere procedimientos que no se encuentren dentro de las


bibliotecas de procedimientos estándar el programador los podrá definir y anexar al
programa o crear sus propias librerías. Estos procedimientos tendrán una forma muy
similar a la forma del programa principal salvo que no se pueden ejecutar
independientemente, tienen que ser invocados. También es posible pasarles argumentos
y ellos a su vez pueden regresar resultados a través de variables a los programas que los
llamaron. De esta forma tendremos que un programa completo constará de un programa
principal, un conjunto de procedimientos y un conjunto de funciones en donde se puede
obtener un diagrama muy parecido al organigrama de una empresa en donde el
programa principal es el gerente general y debajo de él están los gerentes y subgerentes
y así sucesivamente, formando una estructura arbolada. A este árbol le he llamado árbol
de jerarquía de procedimientos y funciones.

De tal manera que un árbol de jerarquía de procedimientos se vería de la siguiente


forma:

3
Programa Principal

/ | \

Procedimiento 1 Procedimiento 2 Procedimiento 3

/ \ \ \

Procedimiento 4 Procedimiento 5 Procedimiento 6 Procedimiento 7

En donde el programa principal puede llamar a los procedimientos 1, 2 y 3


únicamente, el procedimiento 1 llama al 4 y 5, el procedimiento 2 al 6 y el procedimiento 3
al 7.

El programa principal debe reflejar el algoritmo que se está empleando para


resolver el problema ocultando en la mayor medida de lo posible los detalles del lenguaje
de programación. En cambio los procedimientos inferiores se encargarán de resolver las
tareas "sucias" utilizando los recursos detallados del lenguaje. A esto se le conoce como
carga semántica (o de significado), de tal forma que el programa principal sea el que
mayor carga semántica tenga y los procedimientos inferiores la menor, es decir que el
programa principal tendrá el mayor grado de abstracción mientras que los procedimientos
inferiores harán funciones más simples.

El árbol de jerarquía de procedimientos se debe presentar como parte de la


información técnica del programa ya que teniendo únicamente el código será difícil ver la
relación entre procedimientos y el programa principal, cosa que en el árbol se puede ver
de una forma más clara.

Hay programas que manejan recursión, en estos casos no se forma el árbol de


jerarquía de procedimientos y funciones. La recursión es la propiedad de un
procedimiento de invocarse a si mismo.

PALABRAS RESERVADAS

Ya que en un lenguaje se tienen que emplear ciertas palabras para los tipos de
datos y la sintaxis de las estructuras de control no será posible utilizar una de estas
palabras como un identificador de variable, procedimiento o función. Por lo tanto palabras
como “programa”, “entero”, “real”, “carácter”, “comienza”, “termina”, “si” y todas las demás
que utilice el lenguaje se les da el nombre de palabras reservadas y a ninguna variable,
procedimiento o función podrá dársele el nombre de una de ellas.

IDENTIFICADORES

A las variables, procedimientos y funciones habrá que "bautizarlos". A los nombres


con los que las bauticemos se les llama identificadores. Un identificador es el nombre que

3
se le asigna a una variable o a un procedimiento o a una función. Cada lenguaje tiene sus
reglas para los nombres de identificadores. Una regla general es que un identificador no
puede comenzar con un número, esto se debe a que al leer una cadena si el compilador
detecta que el primer carácter es un número sabe que se trata de una cadena que
significa número, en cambio si la cadena comienza con letra tendrá que ser o un
identificador o una palabra reservada.

El nombre con el que se "bautice" a una variable deberá reflejar su función dentro
del programa y es muy importante que sea el nombre adecuado para que el programa se
autoexplique. La tipografía que se recomienda es escribir los identificadores con la
primera letra en mayúscula y las restantes en minúscula. Si el nombre del identificador es
compuesto, concatenar las palabras poniendo en mayúscula la primera letra de cada
palabra, ejemplo:

GradosFahrenheit

Si se desea abreviar el identificador una buena técnica es eliminar las vocales


intermedias, ejemplo:

GrdsFhrnheit

Pascal no es sensible a mayúsculas por lo que el usuario se dará cuenta que


escribir GradosFahrenheit es lo mismo que escribir gradosfahrenheit o
GRADOSFAHRENHEIT, pero es claro darse cuenta de las ventajas de la tipografía
contrastada.

También se puede cortar el nombre de la variable, ejemplo:

Cont para Contador, Temp para temporal, Pot para potencia Fact para Factorial.

El lenguaje de programación C si es sensible a mayúsculas, C tiene su propia


tipografía en donde generalmente todo se escribe con minúsculas y en donde los
identificadores compuestos se separan con el caracter de subrayado, ejemplo:

grados_fahrenheit

La longitud permitida de los identificadores generalmente es muy grande tal que en


general no nos preocuparemos por la longitud de un identificador. En turbo Pascal un
identificador puede tener hasta 64 caracteres.

Así pues, si se emplea bien la tipografía recomendada y si se asigna


adecuadamente los identificadores a las variables, a los procedimientos y las funciones el
programa será autoexplicable. Un programa autoexplicable es aquel que sin necesidad
de comentarios, por su pura lectura, es posible comprender qué es lo que hace, aunque
cabe mencionar que no es mala práctica poner comentarios al programa que ayuden a su
mejor comprensión.

3
También es importante comentar que es buena práctica escribir como comentarios
quién y cuando se escribió el programa con el propósito de llevar un mejor de control de
versiones del programa.

De la misma manera es importante ponerle al nombre del archivo un nombre que


relacione lo que hace el programa, por ejemplo un programa de conversión Celsius
Fahrenheit podría llamarse [Link] en pascal o cel_fahr.c en C.
Lamentablemente cuando se crearon estos compiladores el nombre de los archivos
estaba restringido a ocho caracteres por lo que esta es la longitud más larga que puede
tener el nombre del archivo de un programa.

3
EJERCICIOS CAPÍTULO 6 Fecha de entrega: ______________
Nombre: ________________________________________________________________
1.- ¿Qué estructura tiene un programa? _____________________________________
_______________________________________________________________________
_______________________________________________________________________
2.- ¿De qué elementos está constituido un programa? ____________________________
_______________________________________________________________________
3.- ¿Qué es un enunciado? _________________________________________________
_______________________________________________________________________
_______________________________________________________________________
4.- De un ejemplo de un enunciado de asignación: ______________________________
_______________________________________________________________________
5.- De un ejemplo de enunciado de llamado a procedimiento: ______________________
_______________________________________________________________________
6.- ¿Cuales son los procedimientos estándar en Turbo Pascal? ____________________
_______________________________________________________________________
_______________________________________________________________________
7.- ¿Cómo se le llama a la estructura que forma el programa principal, sus procedimientos
y funciones? _____________________________________________________________
8.- Obtenga el orden e evaluación de la siguiente expresión:
G ← A div B * C + D / E - F

3
9.- Obtenga el orden e evaluación de la siguiente expresión:
G ← A + B * C / Sqr( D + E) - F

10.- Obtenga el orden e evaluación de la siguiente expresión:


G ← A + Sin(-B) * C / D + E - F

11.- Escriba la siguiente expresión de acuerdo a la sintaxis de pseudocódigo y de Pascal


o de C y elabore su árbol de evaluación de operadores:
Radical = b2 - 4ac
Tip: la función cuadrado en Pascal es Sqr (Square). Puede escribirla como función o
como múltiplicación doble.

Pseudocódigo:

3
Turbo Pascal:

C:

12:- Escriba la siguiente expresión de acuerdo a la sintaxis de pseudocódigo y de Pascal


y también elabore el árbol de evaluación:
________
x1 = -b +  _Radical__
2a
Tip: La función raíz cuadrada en Pascal es: SqRt(X), (SquareRoot)

Pseudocódigo:

3
Turbo Pascal:

C:

Desarrolle los siguientes programas utilizando la siguientes tablas y formulas.

SMI SMD
1 Milla 1.6093 Km
1 Libra 2.2 Kg
1 Galón 4.5461 Lt

SMD SMI
1 Km 0.6214 Millas
1 Kg 0.436 Libras
1 Lt 0.26 Galones

C = 5/9 (F – 32)
F = 9/5 C + 32

13.- Un programa que haga la conversión de Millas a Kilómetros.


14.- Un programa que haga la conversión de Kilómetros a Millas.
15.- Un programa que haga la conversión de Libras a Kilogramos.

3
16.- Un programa que haga la conversión de Kilogramos a Libras.
17.- Un programa que haga la conversión de Litros a Galones.
18.- Un programa que haga la conversión de Galones a Litros.
19.- Un programa que haga la conversión de Grados Centígrados a Grados Fahrenheit.
20.- Un programa que haga la conversión de Grados Fahrenheit a Grados Centígrados.
21:- Un programa que calcule la ecuación una recta en función de la variable de entrada
X. M y B deben ser constantes numéricas.
22.- Un programa que calcule el valor de una función de segundo grado también en
función de X.
y = c0 + c1 x + c2 x2
23.- Un programa que calcule el valor de una función de tercer grado también en función
de X.
y = c0 + c1 x + c2 x2 + c3 x3

3
3
7.- LÓGICA PROPOSICIONAL

La lógica fue una de las ciencias desarrollada por Aristóteles en Grecia en el siglo
III antes de Cristo. Básicamente la preocupación de Aristóteles era encontrar las leyes
que regían la mecánica del pensamiento. Así fue como definió el silogismo. Un ejemplo
de silogismo es el siguiente.

Los griegos son hombres.


Aristóteles es griego.
Por lo tanto Aristóteles es hombre.

La lógica fue una esperanza para poder verificar si las estructuras propuestas por
los filósofos eran consistentes. Prácticamente después de Aristóteles los avances de la
lógica estuvieron detenidos hasta el siglo XIX. Varios filósofos y matemáticos
contribuyeron al nacimiento de la lógica moderna como lo son Augustus De Morgan,
George Boole, Leibinitz, Euler, Lambert y Bolzano.

George Boole hace la aportación del álgebra de Boole en donde se puede tener
variables lógicas y trabajar con ellas en expresiones cualquiera que sea su valor, falso o
verdadero. En lógica no es posible que una proposición sea falsa y verdadera al mismo
tiempo, tiene que ser falsa o verdadera pero no ambas.

Augustus De Morgan aporta leyes que trabajan sobre el álgebra de Boole las
cuales permiten manipular expresiones booleanas ya sea para reducirlas o para
encontrar otras expresiones equivalentes. La lógica combinatoria de las computadoras
aprovecha estas leyes para el diseño de la parte combinatoria de las computadoras.

Otros precursores de la lógica moderna fueron Gottlob Ferge, Alfred North


Whitehead, Bertrand Russell, David Hilvert y Kurt Gödel. Kurt Gödel en particular hace
una aportación cuantiosa al demostrar que los sistemas formales de las matemáticas son
incompletos, además demostró que no puede probarse la consistencia de un sistema
formal, lo que mostró que es imposible construir sistemas formales completos y
consistentes. Si desea ampliar su conocimiento en este tema puede consultar el libro,
Introducción a la Computación y a la Programación Estructurada, Segunda Edición,
Guillermo Levine, Mc Graw Hill, punto 5.4 Anexo: visión histórica de la lógica
matemática.

La parte de la lógica que nos interesa estudiar en este momento es la lógica


proposicional o sentencial, que es una interpretación del álgebra desarrollada por Boole.
En lógica proposicional una proposición es una oración o sentencia que puede ser falsa o
verdadera. En esta lógica una variable es un término que puede tomar únicamente dos
valores, falso o verdadero, pero no ambos.
Ejemplo de una variable lógica:

3
A puede representar cualquiera de las siguientes proposiciones:

La pelota es redonda.
El cubo tiene seis caras.
El triángulo tiene cinco lados.

Por lo tanto la variable A puede ser falsa o verdadera dependiendo que


proposición se le asigne.

Las constantes son términos con significado preciso. Las constantes en lógica
proposicional únicamente son dos, falso y verdadero.

Por ejemplo, después de evaluar las proposiciones podemos decir que la


proposición "La pelota es redonda." es verdadera, que la proposición "El cubo tiene seis
caras." es verdadera y que la proposición "El triángulo tiene cinco lados." es falsa.

Sea p una proposición.

Se define la negación de p como no p o ¬p como aquella proposición que es


verdadera si p es falsa y es falsa si p en verdadera. Claramente el operador "negación de
p" es unario; esto es, su rango de acción está limitado a una sola formula proposicional.

Se emplea una notación tabular muy común llamada tabla de verdad para indicar
los valores que toman las expresiones con las diferentes combinaciones de valores
lógicos y los operadores.

La tabla de verdad para la negación es:

p ¬p
V F
F V

Se define la conjunción de dos variables o proposiciones, p y q denotada p ^ q,


como aquella que es verdadera cuando ambas, p y q son verdaderas y falsa en otro caso.

La tabla de verdad correspondiente a este operador es la siguiente:

p q p^q
F F F
F V F
V F F
V V V

3
Se define la disyunción de p y q, denotada p v q como aquella que es verdadera
cuando p o q o ambas son verdaderas y falsa en caso contrario. Esto se conoce como el
"o inclusivo", que en latín se llama vel, de donde proviene el símbolo v.

p q pνq
F F F
F V V
V F V
V V V

Estos dos operadores también se conocen como conectores lógicos ya que


conectan dos proposiciones convirtiéndolas en una.

Cuando en una expresión booleana que contiene variables se sustituyen estas por
constantes ésta se convierte en una función proposicional la cual tiene la característica de
tener uno y sólo uno de los valores permitidos, es decir, una función proposicional
únicamente puede ser verdadera o falsa, pero no ambas.

Ejemplo:
(A ^ B) v C

se convierte en función proposicional cuando sustituimos los valores de A, B y C por:

(la pelota es redonda y el cubo tiene seis caras) o el triángulo tiene cinco lados

Al evaluar cada término el lector puede comprobar que el valor de esta función
proposicional es verdadero.

La tautología tiene la particularidad de que no importa que valores lógicos tomen


las variables que la componen es siempre verdadera, ejemplo:

A v ¬A siempre será verdadera

De forma contraria, la contradicción es una expresión que no importa qué valores


lógicos tomen sus variables será siempre falsa, ejemplo:

A ^ ¬A siempre será falsa

La lógica proposicional continua avanzando y forma una parte fundamental del


campo de la inteligencia artificial y de los lenguajes declarativos como Prolog y Lisp.

Estos conectores lógicos los utilizaremos para formar las condiciones de la


estructura de control de flujo. Para escribir proposiciones también se utilizan los
operadores relacionales. Los operadores relacionales son:

3
Operador Interpretación
= igual que
> mayor que
< menor que
≥ mayor o igual
≤ menor o igual

TABLA DE OPERADORES RELACIONALES

Con estos operadores podemos construir expresiones lógicas como:

A > B, C = D, E ≤ G

En donde las variables pueden ser enteros o reales, con el cuidado de no utilizar el
operador identidad "=" entre reales ya que la probabilidad de que un real llegue a ser
igual que otro es relativamente cero, por lo que esta expresión nunca sería verdadera.

En el álgebra de Boole el operador disyunción es representado por un "+", el


operador conjunción por un "·" y la negación por una comilla. Por lo tanto un ejemplo de
expresión en álgebra de Boole sería:

(A + B ) ∙ C’

Utilizando ésta nomenclatura las leyes de De Morgan son:

(A + B)’ = A’ · B’ y (A · B)’ = A’ + B’

Con estas leyes podemos expresar una proposición en términos de conjunciones o


disyunciones según nos convenga.

Así tendremos expresiones del siguiente tipo:

A > B y C < D o no A > B y no C = D

Las reglas de precedencia para evaluar estos operadores serán las siguientes:

1° La evaluación es recursiva
2º Se evalúa lo que está entre paréntesis
3° Se evalúan los operadores relacionales
4º Se evaúal los operadores de negación
5° Se evalúan los operadores lógicos de izquierda a derecha.

Existen varias nomenclaturas para los operadores lógicos, las pondremos en la


siguiente tabla.

3
Español Inglés Lógica Álgebra de Boole
Proposicional
o or  +
y and  
no not  ’

3
3
EJERCICIOS CAPÍTULO 7 Fecha de entrega: ______________
Nombre: ________________________________________________________________
(La calificación se calcula sobre el número total de respuestas, en este caso, 24.)
1.- ¿Quién el padre de la lógica? _____________________________________________
2.- ¿Qué aportación hace George Boole a la lógica proposicional? __________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
3.- ¿Qué aportación hace Augustus De Morgan a la lógica proposicional? ____________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
4.- ¿Qué es una variable lógica? _____________________________________________
_______________________________________________________________________
_______________________________________________________________________
5.- ¿Qué es una constante lógica? _________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
6.- ¿ Qué es una tabla de verdad? ____________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
7.- ¿ Cómo se define la negación? ___________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
8.- ¿Cómo se define la conjunción? ___________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________

3
9.- ¿Cómo se define la disyunción inclusiva? ___________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
10.- ¿Cómo se define la disyunción exclusiva? __________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
11.- ¿Qué operadores son conectores lógicos? _________________________________
_______________________________________________________________________
12.- ¿Qué es una función proposicional? _______________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
13.- ¿Qué es una tautología? _______________________________________________
_______________________________________________________________________
_______________________________________________________________________
14.- ¿Qué es una contradicción? _____________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
15.- Construya un conjunto de cinco proposiciones a cerca de un mismo objeto que
puedan ser falsas o verdaderas y evalúelas:
i. __________________________________________________________________
ii. __________________________________________________________________
iii. __________________________________________________________________
iv. __________________________________________________________________
v. __________________________________________________________________
16.- Sustituya las variables por los valores de las proposiciones anteriores y evalúe la
siguiente función proposicional:

3
A y no B y C o D y E

17.- Sustituya las variables por los valores de las proposiciones y evalúe la siguiente
función proposicional:
A y no B y (C o D) y E

18.- Construya una tautología con álgebra de Boole: _____________________________


_______________________________________________________________________
19.- Construya una contradicción con álgebra de Boole: ___________________________
_______________________________________________________________________
20.- Construya el árbol de evaluación de la siguiente expresión lógica con A = 5, B = 4, C
=4yD=7
A>ByC≤D

3
21.- Construya el árbol de evaluación de la siguiente expresión lógica con A = 0, B = 4, C
=7yD=7
A>BoC=D

3
8.- ESTRUCTURAS DE CONTROL DE FLUJO Y CONDICIONES

Para resolver un problema la primera tarea es, como ya se mencionó, escribir en


lenguaje natural una descripción del mismo, en qué consiste y los alcances que debe
tener, en sí, qué se espera que haga el programa, es decir, se requiere tener el
enunciado del problema o la especificación del programa que se desea realizar. El
término especificación se utiliza en el área de Ingeniería de Software para dar una
descripción de manera formal de lo que se va a desarrollar. En la industria todo producto
que se fabrica debe tener una especificación. Una especificación es un documento que
reune los datos técnicos, formas, planos, características y mecanismos de
funcionamiento de un producto, ésta debe ser clara y tan libre de ambigüedades como
sea posible.

Cuando un programa de computadora es sumamente complejo y de gran tamaño


generalemnte se le llama sistema. Esto puede llevar a confuciones ya que a las
computadoras que albergan el programa también se les llama sistema o sistema de
computo. Así que es útil diferenciar de un programa “sistema” de un “sistema de
computo”. Comunmente se le llama sistema de computo al conjunto de recursos que
conforman una computadora. Anteriormente los sistemas de gran tamaño estanban
constituidos por una computadora que contenía la memoria principal, la unidad de
procesamiento central y puertos de entrada/salida. Alrededor de la computadora se
encontraban dispositivos de almacenamiento secundario los cuales podrían ser, uno o
varios discos duros y unidades de cinta. También se podían encontrar una o varias
impresoras, terminales de video, modems, etc. Actualmente al área donde se encuentra
el centro de computo de las instituciones, orgnizaciones o empresas se les llama “site” y
cuentan con raks donde se montan los equipos y deben de estar refrigerados y con
plantas de emergencia y pueden alojarse varias computadoras.

Análisis es una palabra que deriba del griego y quiere decir separación. Cuando en
química se habla de análisis se habla de las descomposición de una substancia en sus
componentes. El análisis de sistemas consiste en plantear cuales pueden ser los
diferentes subsistemas que pueden formar el sistema completo. A su vez, cada
subsistema se revisará y se verá si es posible y óptimo que éste este formado de más
subsistemas. El proceso se repite hasta que ya no hay ningún subsistema que se pueda
diseñar con más subsistemas. Cuando ya no hay más subsistemas que analizar el trabajo
hasta este punto quedara terminado. El siguiente problema es elaborar el código de cada
subsistema y acoplarlo al sistema para que el sistema completo trabaje correctamente.

El proceso para elaborar el código de un subsistema o resolver un problema


pequeño no es de análisis. Para solucionar el problema se deben resolver dos
subproblemas. El primero es buscar la forma de representar los objetos del problema del
mundo real con objetos computacionales, el segundo es desarrollar el algoritmo solución.
Una una vez resueltos estos dos puntos se elaboran algunos ejemplos, comenzando con
los más sencillos y terminando con los más complicados. Si hacemos la descripción en
lenguaje natural del algoritmo solución en ella aparecerán los objetos.

3
La tercera etapa consiste en expresar el algoritmo solución en términos
computacionales. En muchas ocasiones ya existe un algoritmo solución por lo que lo
único que hay que hacer es describir el algoritmo en términos computacionales. Cuando
no existe se procederá a desarrollar el algoritmo que lo resuelva.

Una vez teniendo la primera descripción computacional del algoritmo (versión 1) se


prueba el algoritmo con los casos de prueba elaborados anteriormente.

Para hacer la descripción en términos computacionales nos valdremos de las


estructuras de control, el llamado a procedimientos y las invocaciones a funciones.

Las estructuras de control flujo o simplemente estructuras de control son


esquemas que indican la secuencia en que se ejecutarán las instrucciones de un
programa.

Lo primero que resalta en una descripción es su naturaleza secuencial por lo que


la primera estructura de control que veremos es la secuenciación. La secuenciación es
una forma de direccionamiento implícito. Cuando se ejecuta un programa se comienza a
ejecutar la primera instrucción que está en la dirección indicada por un registro llamado
Contador de Programa (PC) en el Microprocesador. ¿Como sabe el microprocesador cual
es la siguiente instrucción a ejecutar? Pues si no hay ningún salto, únicamente se
incrementa el PC y se ejecutará la instrucción a la que apunte, es decir, la siguiente
instrucción en secuencia a la dirección de memoria. En la secuenciación se indica el flujo
poniendo una instrucción después de otra, es decir, la computadora sabe qué instrucción
es la siguiente a ejecutar siguiendo la secuencia en que éstas están escritas.

Pero generalmente en una descripción aparecen decisiones en base a condiciones


por lo que se hace necesaria la segunda estructura de control, la selección. Si pasa ésto
entonces has esto, de otro modo has esto otro.

También podemos apreciar en las descripciones de algoritmos iteraciones


sugeridas por frases como "repite esto hasta que pase ésto", por lo que una tercera
estructura de control necesaria será del tipo iteración condicional.

Tanto la selección como la iteración condicional se evalúan mediante una


condición booleana.

El concepto de enunciado es complejo ya que es un concepto recursivo. Como se


verá más adelante un concepto recursivo es aquel en el que se utiliza el definiens dentro
del definiendum. Veamos, un enunciado es una expresión de un lenguaje. Un enunciado
puede estar compuesto a su vez de enunciados. Los enunciados se pueden organizar en
secuencia. Los enunciados más simples son los enunciados de asignación y de llamado a
procedimiento. Las estructuras de control también son enunciados. Un bloque de
enunciados también es un enunciado. Una estructura de control generalmente contiene
dentro enunciados. Por lo tanto un programa también es un enunciado. Las estructuras
de control dirigen en flujo de ejecución de los enunciados. El enunciado más simple sobre
el que trabajan las estructuras de control de flujo es el enunciado de asignación, es decir,

3
siempre habrá al menos un enunciado de asignación dentro de las estructuras de control
de flujo de los procedimientos o funciones de nivel semántico más bajo, no tiene sentido
una estructura de control que no tenga enunciados adentro. Un enunciado de asignación
como su nombre lo indica se asigna el valor de una expresión a una variable, ejemplo:

A←1

En los lenguajes hay un símbolo para la asignación y otro para el relacional de


igualdad, en Pascal se implementa la operación de asignación con la secuencia de
símbolos ":=" y el relacional de igualdad con el símbolo "=", el empleo de este símbolo lo
veremos más adelante.

Otro tipo de enunciado es el llamado a procedimiento, ejemplo:

Lee( A)

En este caso Lee es un procedimiento de entrada/salida lo mismo que Escribe.

Utilizaremos la siguiente notación para mostrar la sintaxis de las estructuras de


control de flujo. Un enunciado cualquiera lo representaremos con la letra e y cuando haya
necesidad de diferenciar entre varios enunciados estos se numerarán, ejemplo: e1, e2,.....,
en. Una condición booleana se representa con la letra mayúscula C.

Los elementos más básicos de la programación son los enunciados, también


llamados sentencias o proposiciones. Y éstos a su vez solo pueden ser de tres clases,
enunciados de asignación, llamados a procedimiento y estructuras de control. Estos se
pueden ver como los ladrillos con los que se construye un programa. Podríamos construir
un programa con tres tipos de enunciados. Un enunciado, sentencia o proposición es una
instrucción imperativa que se le da a una computadora. En general como ya se mencionó
manejaremos enunciado, sentencia y proposiciones como sinónimos en éste campo.

Existen dos maneras de representar las estructuras de control ya descritas, una


mediante diagramas de flujo y otra mediante pseudocódigo.

En un principio no existían los lenguajes estructurados, el primer método que se


implementó para manejar el flujo de los programas fueron los diagramas de flujo. Estos
son más intuitivos pero con el tiempo se comenzaron a ver sus desventajas. Cuando un
programa crecía, el diagrama de flujo se hacia inmanejable por lo que se buscaron otras
alternativas de programación.

Lo que se encontró fue que sólo eran necesarios ciertos patrones de los diagramas
de flujo y a éstos se les dio el nombre de estructuras de control de flujo o simplemente
estructuras de control. Con éstas estructuras se diseñó un metalenguaje estructurado al
cual se denominó pseudocódigo. Con este lenguaje se buscaba tener un lenguaje
genérico universal para poder representar algoritmos y se encontró también que es más
conveniente utilizar el pseudocódigo que los diagramas de flujo ya que se pueden obtener

3
programas más claros, óptimos, fáciles de depurar y optimizar. Por todo lo anterior los
diagramas de flujo quedaron en el pasado.

Es importante hacer notar que al ser el pseudocódigo un lenguaje genérico se


pensó que sería posible escribir todos los algoritmos en este metalenguaje y de éste
codificarlos en cualquier lenguaje de programación formal. De esta manera únicamente
habría que tener una sola versión de los algoritmos en pseudocódigo que podría ser
codificada a cualquier lenguaje formal y no sería necesario tener una versión del
algoritmo en cada lenguaje que existiera. Hay que hacer notar que en este tiempo todavía
no había lenguajes estructurados por lo que había que codificar el programa en
pseudocódigo en un lenguaje no estructurado.

El pseudocódigo requiere de ciertos símbolos privilegiados que ya tienen un


significado preciso y preestablecido. A tales indicadores del pseudocódigo se les conoce
como palabras reservadas o clave.

Será necesario que exista una palabra reservada para la selección otra para la
iteración condicional y otras para las estructuras de control que veremos más adelante.
Por ejemplo la palabra si que se utiliza para la selección es una palabra clave ya que
tiene un significado preestablecido a diferencia de un identificador el cual puede ser
asignado a cualquier variable, procedimiento o función. Un identificador es el nombre con
el que se reconoce a una variable, función o procedimiento y la regla es que debe de
comenzar con letra, ejemplo: Temperatura, Presión, Volumen, Alumno1, etc.

En virtud de que las palabras reservadas son palabras que hablan acerca de otras
adquieren la categoría de metapalabras.

A continuación se describen las tres estructuras de control empleando las tres


formas ya explicadas:

Secuenciación e1
e2
o bien
e1; e2

Selección si C entonces e1
otro e2

Iteración condicional repite e hasta C

Como se puede observar, existen palabras reservadas para la selección y para la


iteración condicional pero no para la secuenciación ya que basta escribir un enunciado en
cada renglón o escribirlos en el mismo renglón separados por punto y coma, utilizando el
";" únicamente para separarlos.

Observe que cada una de estas estructuras de control tiene un solo punto de
entrada y un solo punto de salida. Esto nos ayudará para armar programas completos

3
uniendo salidas con entradas para formar cadenas de enunciados estructurados
acomodados en secuencia.

Como ya se dispone de estructuras de control básicas se procederá a hacer uso


de ellas combinándolas de diversas maneras para escribir programas completos. Para
este fin existe una regla fundamental de composición que dice lo siguiente:

"Es posible combinar las estructuras de control de secuenciación, selección e


iteración condicional para formar nuevas estructuras de secuenciación, selección e
iteración condicional".

Es decir, es posible hacer una secuencia de selecciones e una iteraciónones


condicionales o es posible hacer una secuencia de una selección y una iteración
condicional.

Si esta regla de composición parece rara es por que es recursiva. Una definición
es recursiva si emplea el definiens dentro del definiendum, o en otras palabras, si dice
como obtener conceptos nuevos empleando para tal fin el mismo concepto que se intenta
definir. Un razonamiento recursivo tiene dos partes: una base y la regla recursiva de
construcción. La base no es recursiva y es el punto tanto de partida como de terminación
de la definición.

Podría considerarse la siguiente la regla de formación de estructuras de control


válidas:

Base: La secuenciación, la selección y la iteración condicional son estructuras de


control válidas que pueden ser consideradas como enunciados.

Regla: Las estructuras de control que se pueden formar combinando de manera


válida la secuenciación, selección e iteración condicional también serán válidas.

Esto da origen al concepto de programación estructurada. Un programa estará


bien construido si está formado por estructuras de control válidas, de acuerdo con la base
y la regla precedente.

Para ilustrar el uso de las estructuras de control como regla de formación


consideremos lo siguiente:

Tenemos dos enunciados, e1 y e2.

e1
e2

Una secuencia de enunciados también es un enunciado. Si agregamos un tercer


enunciado ésta seguirá siendo una secuenciación si consideramos a los primeros dos
como uno solo y aplicando la regla de la secuenciación obtenemos que tres enunciados
seguidos también son una secuenciación.

3
e1
e2
e3

Al agregar un enunciado, el conjunto de enunciados se puede seguir viendo como


un enunciado. De la misma manera podremos tener secuencias de iteraciones,
selecciones de secuencias, secuencias de selecciones, iteraciones de selecciones y
todas las combinaciones posibles de estas tres estructuras de control básicas.

Si aplicamos las reglas básicas para construir estructuras de control válidas


podemos ver que todo programa bien construido se puede reducir a un solo enunciado.

A su vez, podremos decir que cualquier estructura de control, simple o compuesta


que esté bien formada es un enunciado y también que el alcance sintáctico de un
enunciado es de un enunciado. El alcance sintáctico es el dominio donde tiene acción un
enunciado, por lo tanto una estructura de control de selección solo podrá contener uno o
dos enunciados y una iteración condicional solo un enunciado (esto puede ser confuso,
pero si se considera que una estructura de control bien formada siempre se podrá
considerar como un enunciado esto se puede ver más claro).

Entonces, para lograr que existan "más de un enunciado" dentro de estas


estructuras de control utilizaremos los llamados metaparéntesis. Con estos podremos
enmarcar un conjunto de enunciados convirtiéndolos en un solo enunciado, es decir, con
estos metaparéntesis podremos convertir una secuenciación en un solo enunciado. Estos
metaparéntesis son dos nuevas palabras del pseudocódigo y son "comienza" y "termina".

De esta forma podemos tener bloques de enunciados dentro de cualquier


estructura de control donde aparece un enunciado, ejemplo:

si C entonces
comienza
e1
e2
termina
otro
comienza
e3
e4
termina

Si una estructura de control compleja está bien formada seguirá teniendo una sola
entrada y una sola salida. De la misma manera, si un programa está bien formado seguirá
teniendo una sola entrada y una sola salida.

Utilizando las reglas de formación el número de estructuras de control nuevas que


podemos formar es infinito. Claro que en la realidad habrá un límite técnico para la

3
profundidad, pero éste generalmente es elevado por lo que no nos preocuparemos por
ésto.

Para marcar la profundidad se utiliza lo que se conoce como indentado. El


indentado es un sangrado que se deja para indicar que un enunciado está dentro de otro.
A esta propiedad le llamaremos pertenencia de las estructuras de control. Cuando un
enunciado se encuentre dentro de otro diremos que pertenece o que está anidado o qué
está dentro o que de la estructura de control exterior.

Ejemplos de anidamiento:

repite
si C1 entonces e
hasta (C2)

En este caso tenemos una selección dentro de un repite.

Las estructuras de control adicionales del tipo iteración condicional son dos:
mientras y para, con la diferencia de que primero evalúan la condición booleana y luego
ejecutan el (o los) enunciados asociados hasta que se cumple la condición de
terminación.

Se puede demostrar que la estructura de control “repite” no es primitiva


componiéndola como la secuenciación de un enunciado simple y una “iteración
condicional mientras” para obtener un programa equivalente:

e
mientras (C) e

que primero ejecuta una vez el enunciado y luego averigua si debe o no continuar
haciéndolo.

La segunda versión difiere de la primera en cuanto a la forma como se controla la


iteración, que ahora está determinada por consideraciones numéricas con el valor de un
índice de control de la siguiente manera:

ejecuta I = LimitInferior, LimiteSuperior


e

Este pseudocódigo dice "para I = LimiteInferior a LimiteSuperior ejecuta el


enunciado e".

El lector podrá comprobar que éste pseudocódigo es la abreviatura de este otro:

I = LimiteInferior
mientras(I < LimiteSuperior)
comienza

3
e
I=I+1
termina

Con lo que queda claro que no es una estructura de control primitiva.

Por el lado de la selección existe una ampliación llamada caso que es la


abreviatura de:

si V = 1 entonces e1
otro si V = 2 entonces e2
otro si V = 3 entonces e3
otro ....

En efecto, esta construcción anidada no es más que una prueba de opción múltiple
sobre el valor de la variable V y que también puede representarse con esta estructura
completa:

caso V de
constante 1: e1
constante 2: e2
.
.
constante n: en
fin-caso

La cual in extenso quiere decir: en caso que la variable sea igual a la constante 1
ejecuta el enunciado 1, en caso de que sea igual a la constante 2 ejecuta el enunciado 2
y así sucesivamente; Esta estructura de control se utiliza cuando se tienen varios si's
anidados que dependen del valor de una variable haciendo más claro el código y
quitando el problema del indentado. El caso es muy usado menús de opciones. Esta
estructura abrevia gran cantidad de si's anidados.

A continuación agregamos la sintaxis del pseudocódigo definida por Guillermo


Levine Gutierrez en su libro de Introducción a la Computación y a la Programación
Estructurada, Ed. Mac Graw Hill.

SINTAXIS DEL PSEUDOCÓDIGO

Se utiliza “!” para comentarios


Las palabras reservadas van subrayadas
“e” representa cualquier enunciado, sentencia o proposición

Metaparéntesis

comienza y termina

3
Estructuras de Control

Estructura de Control de Flujo Secuencial

Salto de línea es separador de enunciados


Si están en la misma línea utilizar como separador “;”

Estructuras de Control de Flujo Selectivas

si condición entonces e
si condición entonces e otro e
caso V de
A1: e
A2: e
A3:e
fin-caso

Donde A puede ser un real o una condición:


Ejemplo:
caso ALFA de
1.6 : tasa = factor * 2
< 38 : comienza
lee beta
escribe zeta
tasa = factor * 3
termina
: tasa = 0
fin-caso

Estructuras de Control de Flujo Iterativas

mientras (condición) e
repite e hasta (condición)
ejecuta i = Li, Ls e

Condiciones

En la estructura de control si la condición no va entre paréntesis


En las estructuras de control mientras y repite la condición sí va entre
paréntesis

Ejemplo

si LISTA(ap) = VALOR entonces band = 1 otro ap = ap + 1


mientras(LISTA(ap) <> VALOR y ap <= FIN) ap = ap + 1

Se utiliza el “=” tanto para comparación como para asignación.

3
Símbolos Relacionales
= igual
> mayor que
< menor que
>= mayor o igual que
<= menor o igual que
<> Diferente

Conector Lógico
o disyunción
y conjunción
no negación

Llamadas a procedimiento

proc principal
declaraciones
proposiciones
llama uno
proposiciones
fin.

proc uno
declaraciones
proposiciones
regresa
fin.

3
El paso de parámetros únicamente se hace por referencia, no se indica nada.

proc principal
entero a, b, resultado
lee a, b
llama suma(a, b, resultado)
escribe “a + b = ”, resultado
fin.

a, b y resultado son parámetros actuales o reales o argumentos

proc suma(s1, s2, r)


entero s1, s2, r
r = s1 + s2
regresa
fin.

a, b y resultado son parámetros actuales


s1, s2, r son parámetros formales

Utiliza paréntesis tanto para arreglos como para argumentos

Ejemplo:

entero LISTA(10)

Es sensible a mayúsculas por lo tanto la variable LISTA es diferente de lista

No hay restricciones en cuanto a asignaciones con diferentes tipos de datos, es


decir un entero puede almacenarse en un real y un real puede almacenarse en un entero

Tipo de Dato
entero
real
caracter

Con esto terminamos la descripción de la sintaxis del pseudocodigo de Guillermo


Levine.

Los criterios para utilizar las estructuras de control repetitivas son los siguientes:

Si se sabe de antemano el número de iteraciones que va a ejecutar el bucle se


utilizará la estructura de control para.

Si no se conoce de antemano el número de iteraciones se utilizarán la estructuras


de control repite o mientras.

3
Si se requiere que no se ejecute ninguna iteración si no se cumple la condición se
debe de utilizar un mientras, en otro caso se usará un repite.

Generalmente las descripciones de algoritmos en lenguaje natural están hechas de


modo que se hace algo hasta que alguna condición se cumple por lo que lo más intuitivo
al hacer la descripción de un algoritmo en términos computacionales es utilizar estructura
de control repite-hasta.

La estructura de control “ejecuta” actualiza la variable de control automáticamente


la finalizar el ciclo a diferencia del repite y el mientras, que no lo hacen.

Note que cualquier estructura de control también es un enunciado, por lo que si


tenemos una secuencia de estructuras de control deberán separarse por ";".

Ahora jugaremos con los términos computacionales para mostrar como una receta
de cocina se puede escribir en términos computaciones. Tendremos una descripción en
lenguaje natural, la cual traduciremos en una descripción en términos computaciones. La
receta es la siguiente:

Huevos a la Inglesa

6 huevos frescos.
1 ½ tazas de queso gruyere rallado.
¼ de cucharadita de mostaza preparada.
1 ½ tazas de crema fresca.
2 cucharadas de harina cernida tres veces.
2 cucharadas de mantequilla.
Sal y pimienta al gusto.

La mantequilla se pone en una cacerola y ya que está derretida se le agrega la


harina y se mueve hasta que esté ligeramente dorada. Se le agrega la leche, poco a poco
y sin dejar de mover para que no se formen grumos. Ya que está cocida y queda como un
atole espeso, se sazona con la sal y la pimienta y se retira del fuego.

En un molde de loza refractaria, engrasado con bastante mantequilla, se van


partiendo los huevos, procurando que éstos no se junten mucho; se espolvorean con sal,
pimienta y el queso y se cubren con la salsa.

Se pueden servir en un platón o en moldecitos individuales.

La descripción en términos computacionales es:

Programa Cocina unos Huevos a la Inglesa

comienza
Consigue 6 huevos frescos.

3
Consigue 1 ½ tazas de queso Gruyere rallado.
Consigue ¼ de cucharadita de mostaza preparada.
Consigue 1 ½ tazas de crema fresca.
Consigue 2 cucharadas de harina cernida tres veces.
Consigue 2 cucharadas de mantequilla.
Consigue Sal y pimienta.

Pon la mantequilla en una cacerola;


Derrítela;
Agrégale (Harina);
repite
Mueve
hasta que esté ligeramente dorada;
Agrégale (Leche, poco a poco y sin dejar de mover para que no se formen grumos);
repite
Bate
hasta que esté cocida y quede como un atole espeso;
Sazónalo (Sal)
Sazónalo (Pimienta);
Retíralo (Fuego).
Engrasa un molde con bastante mantequilla;
Parte los huevos y ponlos ahí procurando que estos no se junten mucho;
Espolvoréalos (Sal);
Espolvoréalos (Pimienta);
Espolvoréalos (Queso);
Cúbrelos (Salsa);
Ponles (trocitos de mantequilla encima):
Mételos al horno caliente a (350°)
repite
Retardo
hasta que cuajen;
Escribe('¿Como los quiere servir, si en un platón o en moldecitos individuales?');
Lee( Respuesta)
si Respuesta = 'en un platón' entonces sírvelos en un platón
de otra forma sírvelos en moldecitos individuales;
fin.

Observe que esta descripción está hecha a través de ordenes, esto se debe a que
en realidad en la programación se le dan ordenes a la computadora, es por esta razón
que a este paradigma de programación se le llama programación imperativa, por lo tanto
no está en 3a persona, sino en 2a.

También se puede apreciar que en términos computacionales no es posible dar


órdenes complejas, es decir dos instrucciones simultáneamente. Es necesario dar
instrucción por instrucción ya que el nivel de reconocimiento de la gramática no permite
todavía reconocimiento en lenguaje natural.

3
Y finalmente es la misma descripción excepto que aparecen estructuras de control
para dirigir el flujo del programa.

Si tuviéramos un robot con la capacidad de interpretar y ejecutar las instrucciones


cada vez que le solicitáramos unos huevos a la inglesa, este buscaría en su base de
datos la receta (el programa) y si lo tiene, ejecutaría la receta entregándonos unos ricos
huevos a la Inglesa, y esto sería las veces que nosotros se los pidamos.

Esto tiene varios comentarios. Primero, que la receta en términos computacionales


es primero que nada una descripción, pero que teniendo la descripción en esta forma y
teniendo una máquina capaz de interpretar la descripción nos podemos liberar de la
monserga de preparar los huevos a la Inglesa.

Tal vez existan personas a las que les guste cocinar, pero hay trabajos rutinarios
que generalmente a nadie le gusta hacer como lavar la ropa, plancharla, limpiar la casa y
lavar los platos, tender las camas, por lo que sería muy interesante construir autómatas
que fueran capaces de hacer este trabajo liberándonos del trabajo rutinario.

Claro que es probable que de todos modos tengamos que supervisarlos, ya que
estos autómatas no tendrían la capacidad de razonar y no podrían resolver ciertos
problemas que no hayan sido contemplados en el programa como sería que una sabana
se rompió o que la plancha no calienta cuando no hay energía eléctrica.

También podemos agregar que aunque la receta ya esté en lenguaje natural o en


términos computacionales, la receta no son los huevos a la inglesa, es una forma de
representar los huevos a la inglesa, pero con la receta podemos hacer los huevos a la
inglesa las veces que queramos y en teoría, si se sigue correctamente, los huevos
saldrían exactamente iguales a los que hizo el que creo los huevos a la inglesa. Esto es a
lo que Levine se refiere como el cierre del ciclo de la transmisión del conocimiento que
consiste en lo siguiente:

Un individuo ha adquirido conocimiento y ha desarrollado un método para hacer


algo y nadie más lo tiene.

Este individuo especifica su método en una forma clara, precisa y completa


escribiéndolo en lenguaje natural.

Otro individuo lee la especificación y trata de comprenderla (interpretarla).

La sigue al pie de la letra, y si la descripción del método es clara, precisa y


completa, y si además el segundo individuo la sigue sin cometer errores entonces se
habrá logrado la transmisión del conocimiento al lograr reproducir los mismos resultados
del primer individuo al segundo.

individuo uno individuo dos

Proceso de transmisión del conocimiento

3
El proceso se da de la siguiente manera:

El individuo uno tiene un conocimiento.

El individuo uno lo representa en su mente con elementos del lenguaje.

Para transmitirlo genera una descripción de esa representación.

Emite la descripción en lenguaje natural.

El otro individuo la recibe e interpreta esa descripción generando la misma


representación en su mente.

Si la representación es la misma ¡Se ha llevado a cabo el proceso de transmisión


de conocimiento! De hecho, de esta forma es como los seres humanos enseñamos y
aprendemos, aunque lo hacemos sin tener conciencia de cómo lo hacemos.

En este caso un programa es una descripción que metemos a la computadora, y si


la descripción es correcta y completa la computadora logrará reconstruir el método para
obtener los mismos resultados que nosotros podemos obtener manualmente con sus
elementos, así que en cierta forma le estamos transfiriendo nuestro conocimiento,
además de que la humanidad ya cuenta con una máquina que puede aceptar
descripciones y ejecutarlas, y no nada más eso, ya tenemos una forma de probar si
nuestras descripciones son correctas y completas. Este punto es fundamental para las
ciencias de la computación.

Incluiremos una tabla para indicar las diferentes formas de representar los
operadores lógicos en Pascal y C.

Operador Pascal C
y And &&
o Or ||
no Not !

Tabla de operadores lógicos

3
Relacional Pascal C
= = ==
> > >
< < <
≥ >= >=
≤ <= <=

Tabla de símbolos relacionales

Operador Pascal C
+ + +
- - -
Multiplicación * *
División entera Div
División / /
Módulo Mod %

Observe que la estructura de un programa son una serie de cajas que obedecen
solo a dos formas de agruparse, una en forma secuencial y otra en forma de una caja que
esta adentro de otra caja. Con estas dos propiedades podemos formar bloques que
únicamente tendrán una entrada y una sola salida, además de que producirán secciones
de código claras que solo efectúan una función, pero que esta función la realizan bien.

De esta manera la forma general de un programa si enmarcáramos todos los


enunciados simples y las estructuras de control quedara de la forma siguiente:

Enunciado

Estructura de control iterativa

3
EJERCICIOS CAPÍTULO 8 Fecha de entrega: ______________
Nombre: ________________________________________________________________
1.- En el siguiente programa marque en un recuadro rojo las sentencias de asignación,
con verde los llamados a procedimiento, con azul la estructura de control iterativa. Nota:
marque la estructura de control desde donde comienza hasta donde termina.

programa Lineal;
entero X, Y;
comienza
ejecuta X = 0, 10
comienza
Y=2*X+5
escribe Y
termina
termina

2.- Obtenga una receta de cocina y transcríbala:


_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________

3
3.- Represente la misma receta en términos computacionales, es decir con estructuras de
control: _________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
4.- Desarrolle un programa que diga la relación cardinal de dos números suministrados,
es decir, si el primero es mayor que el segundo, si son iguales o si el segundo es mayor
que el primero.
5.- Desarrolle un programa que encuentre la relación cardinal de tres números enteros
suministrados. Ejemplo: A es mayor que B y B es mayor que C

3
6.- Desarrolle los programas de conversión del capítulo 6 pero que escriban una tabla de
conversión desde un valor inicial entero, dado por el usuario, hasta el valor final entero,
también dado por el usuario, con incrementos de uno en uno.
7.- Desarrolle un programa que convierta un número en base decimal a cualquier base
que el usuario requiera, de base 2 a base 9. Ejemplo: 20 10 es 101002. No importa que el
número salga invertido, solo tiene que notificar el programa al usuario que el número se
se escribirá invertido.
8.- Haga un programa que encuentre la suma de la serie armónica hasta el elemento que
el usuario indique (efecto acumulador).
n

Serie armónica ∑ 1/i


i=1

9.-Hacer un programa que despliegue la serie de Fibbonacci hasta el elemento de la serie


que el usuario indique a partir del tercer término, es decir si dice uno tiene que dar como
salida 1, 1, 2, si dice 2 tiene que dar como salida 1, 1, 2, 3, y así sucesivamente.
Serie de Fibbonacci: 1, 1, 2, 3, 5, 8, 13, ............
10.- Escribir un programa que permita encontrar el máximo común divisor (MCD) de dos
números mediante el algoritmo de Euclides. El algoritmo de Euclides es el siguiente: al
dividir A entre B se obtiene un cociente Q y un residuo R. A toma el valor de B, B toma el
valor de R. Se repite esta operación hasta que el residuo es cero. El último divisor es el
MCD.
11.- Elaborar un programa que encuentre las raices de una ecuación de 2º grado.

3
3
9.- PROCEDIMIENTOS, FUNCIONES, PASO DE PARÁMETROS, VARIABLES
GLOBALES, VARIABLES LOCALES, ALCANCE SINTÁCTICO Y RECURSIÓN.

La programación es una herramienta muy poderosa ya que con ella se pueden


hacer programas con muy alto grado de complejidad. Esta complejidad irá creciendo a
medida que vayamos ganando experiencia en el arte de hacer programas. Nuestros
primeros programas serán sencillos, pero a medida que progresemos nuestros
programas serán más complejos.

Es importante conocer el manejo de las funciones y los procedimientos antes de


aprender a programar ya que serán herramientas importantes en el ejercicio de la
programación. Utilizaremos un método de programación que yo llamo programación en
lenguaje natural, no por que se programe en lenguaje natural ( como el lenguaje en el que
hablamos) sino porque programaremos lo más similarmente posible a la forma en la que
hablamos, esto lo explicaremos más adelante cuando veamos métodos de programación.

A partir de aquí utilizaremos un pseudocódigo con la sintaxis de turbo Pascal con


el objeto de que la codificación en Turbo Pascal sea directa. El operador de asignación
“:=” de Turbo Pascal lo representaremos por “←” y utilizaremos el símbolo “;” para
separar enunciados.

Las herramientas fundamentales para poder hacer programas más complejos son
las funciones y los procedimientos. Una función es un segmento de código que evalúa
una expresión de acuerdo a uno o más argumentos que se reciban y el resultado de la
evaluación se regresa y se sustituye en el lugar donde fue invocada la función.

Ejemplo:

función Medio(LimiteInferior, LimiteSuperior): integer

comienza
Medio ← (LimiteSuperior - LimiteInferior) / 2
termina

A ésta parte se le llama la definición de la función.

Después podremos invocar a la función en cualquier parte del programa de la


siguiente manera:

A los parámetros de la definición les llamaremos parámetros formales.

Posición ← LimiteInferior + Medio(LimiteSuperior, LimiteInferior)

A los argumentos de la invocación les llamaremos parámetros actuales.

3
Los parámetros formales y actuales pueden tener en general nombres diferentes.
Esto se debe a que la definición de la función o el procedimiento puede ser muy general
mientras que las invocaciones pueden ser muy particulares.

Cabe recordar que el sueño de Charles Babbage era construir una máquina en la
que se pudiera cambiar la función de cálculo, observe que esto se puede hacer
fácilmente cambiando la definición de la función.

Un procedimiento es un segmento de código que puede o no recibir argumentos y


que realiza un proceso sobre ciertos datos, es una unidad autocontenida de código ( o
sea, dice todo lo que se requiere para entenderlo) y que tiene la característica de no ser
directamente ejecutable, sino que debe ser llamado para efectuar sus funciones. A los
procedimientos se les da también el nombre de subrutinas o módulos. Generalmente la
forma de regresar los resultados se hace a través de datos compartidos con los
procedimientos que lo llamaron, a esta forma de pasar argumentos se le llama paso de
parámetros por referencia. Para indicar en Turbo Pascal que el paso de parámetros se
hará por referencia se pone la cadena var al inicio de la lista de variables en la definición
del procedimiento.

Generalmente también es necesario enviar ciertos datos que serán requeridos por
un procedimiento pero que no interesan al momento de finalizar el procedimiento, a esta
forma de enviar argumentos se le llama paso de parámetros por valor. En el paso de
parámetros por valor el procedimiento o la función realizan una copia del valor, de tal
forma que el valor en la variable original permanecerá inalterado. Para indicar que el paso
de parámetros es por valor no se tiene que hacer nada, solo poner el nombre de la
variable y su tipo como parámetro.

Podemos modelar los procedimientos como si fueran un sastre. El sastre es el


procedimiento que procesa la tela y la transforma, pero es necesario darle elementos al
sastre para que pueda trabajar, un elemento es la tela, la cual él va a procesar y la cual
va a regresar pero convertida en un traje, por lo tanto la tela es un argumento que
debemos pasar por referencia o variable ya que tiene que regresar transformada. Pero no
solo eso, también necesitamos darle al sastre las medidas, ya que sin las medidas el
sastre no sabrá como transformar la tela. Así, pasaremos al sastre las medidas. El sastre
hará una copia de las medidas en un papelito las cuales no es importante que regrese.

Ejemplo de procedimiento:

procedimiento Intercambia (var X, Y: entero)


var Temp: entero
comienza
Temp ← X;
X ← Y;
Y ← Temp
termina

3
En este procedimiento el paso de parámetros se hace por referencia ya que es
necesario que después de ejecutado el procedimiento las variables registren la
actualización. Si no se antepusiera la palabra “var” en la lista, el paso de parámetros se
haría por valor no generando ningún cambio después de ejecutar el procedimiento..

A la especificación de las variables que se reciben como argumentos se le llama


especificación de los parámetros formales. A los argumentos enviados al invocar la
función o el procedimiento se les llama parámetros actuales.

Esto solo es valido para Pascal ya que en C no existen procedimientos, todas son
funciones, pero es posible invocar a una función de la misma manera que se invoca a un
procedimiento en Pascal.

VARIABLES GLOBALES Y VARIABLES LOCALES

Un programa consta generalmente de código y de una serie de variables en las


cuales se almacenarán datos para ser procesados. En ocasiones el problema requiere
que existan una serie de datos durante toda la ejecución de un programa, esto es posible
hacerlo mediante lo que se llaman variables globales.

Un ejemplo de esto podría ser un programa que simula un juego de ajedrez. Será
necesario modelar el tablero y las piezas de alguna manera. El tablero y las piezas deben
de estar presentes durante toda la ejecución del programa.

En general se ha establecido como buena práctica el tener el menor número


posible de variables globales, y si es posible ninguna, ya que tener una variable global
implica que cualquier procedimiento puede alterarla y en caso de haber un mal
funcionamiento sería muy difícil saber cual módulo la está afectando inadecuadamente,
además de que se viola el principio de autocontenidez que consiste en que todas las
variables de las que se hable en un procedimiento deben de estar declaradas como
variables locales o deben ser parámetros formales. Se puede citar una variable global en
cualquier módulo sonando esto como algo fuera de contexto ya que la declaración de esa
variable no estará cerca y será difícil recordar su tipo y el programa se hará más difícil de
comprender. Así que solo en casos estrictamente necesarios se declararán variables
globales.

Es natural que para que un procedimiento pueda hacer su trabajo necesite


contadores, índices, variables temporales, etc. por lo que normalmente se requerirán
declarar variables que únicamente estarán vigentes solo cuando el procedimiento se está
ejecutando. A éste tipo de variables se les llama variables locales. Todas las variables
declaradas dentro de un procedimiento serán variables locales. Si una variable aparece
en un procedimiento sin haber sido declarada ni haber sido pasada por argumentos el
compilador tratará de resolver buscando hacia arriba la variable más cercana que tenga
el mismo nombre. A ésto se le llama el alcance sintáctico de una variable, lo cual quiere
decir que una variable puede ser invocada fuera del ámbito donde fue declarada aunque
de nuevo esto rompe el principio de auto-contenido que deben cumplir como política los
procedimientos.

3
ALCANCE SINTÁCTICO

El alcance sintáctico de un identificador es la sección de código donde éste


identificador es reconocido. El alcance sintáctico de una variable global es todo el
programa. El alcance sintáctico de una variable local es únicamente el procedimiento
donde está declarada. Aunque generalmente las variables globales tienen nombres muy
particulares, Turbo Pascal da la flexibilidad de que existan variables globales y locales
con el mismo identificador. La forma de resolver del compilador a qué variable se refiere
una línea de código es buscando la declaración más cercana hacia arriba, en éste caso,
si el programa se encuentra ejecutando una instrucción del procedimiento la declaración
a la que se hará referencia será a la local. Solo en caso de que no se haya declarado la
variable como local en un procedimiento se estará haciendo referencia a la variable
global.

Aunque si se utiliza un índice, por ejemplo "I" en varias partes del programa, es
tentador definirlo como global, pero no es recomendable hacer esto ya que se violaría el
principio de auto-contenido. Es mejor definir la variable en cada procedimiento cada vez
que se vaya a utilizar aunque esto parezca redundante.

Por otro lado las variables globales, si es que son necesarias, deben tener
nombres muy particulares para evitar confusiones con variables definidas localmente.

LA RECURSIÓN

La recursión es la invocación a si misma de la función o el procedimiento desde


adentro. Existen problemas que se pueden resolver mediante algoritmos recursivos. Las
funciones que utilizan la recursión básicamente constan de dos partes, el caso general y
el caso límite. Algunos algoritmos no recursivos se pueden escribir en forma recursiva, tal
el es el caso de una función potencia o factorial.

Una función potencia la podemos escribir en forma iterativa como:

función Potencia(N, M: entero): entero


var
I, X: entero
comienza
X←N
para I ← 1 a M has
X←X*N
Potencia ← X
termina

En forma recursiva ésta función se escribiría:

función Potencia(N, M: entero): entero


comienza

3
si M = 1 entonces
Potencia ← N
otro
Potencia ← N * Potencia(N, M -1)
termina

Es importante mencionar que la recursión en una función o un procedimiento


requerirán más recursos de la máquina como memoria por lo que es recomendable
utilizarla sólo en casos en donde la recursión sea la única solución algorítmica del
problema como es el caso del problema de las torres de Hanoi o cuando la simplicidad
del algoritmo recursivo supere por mucho al iterativo.

El problema de las torres de Hanoi es un buen caso de aplicación de la recursión.


el problema consiste en pasar 64 discos de diferente tamaño de un poste a otro utilizando
un poste central y en donde la única regla es que no es permitido poner un disco más
grande arriba de otro más chico. Los 64 discos van disminuyendo en tamaño conforme
son apilados.

El problema se resuelve creando un procedimiento que pase la torre de altura H al


poste deseado pasando por el poste restante. Considerando que el procedimiento se
puede reinvocar y que se le puede solicitar mover los discos restantes del poste fuente al
poste destino, pasando por el poste restante, el problema se reduce a mover un solo
disco.

El procedimiento sería:

MuevePila(var Fuente, Destino, Paso: arreglo; H: entero)

Suponiendo que éste procedimiento existe entonces Hanoi se escribiría así:

programa Hanoi
comienza
MuevePila(A, C, B, H)
termina

Donde el poste de la izquierda se representa por A, el de en medio por B y el


derecho por C.

Si consideramos que el disco inferior no se mueve por el momento, podemos


considerar el problema de mover la pila de arriba al poste intermedio, el disco inferior al
poste destino y de nuevo la pila superior al poste destino. Entonces MuevePila se puede
escribir como:

procedimiento MuevePila(var Fuente, Destino, Paso: arreglo; H: entero)

comienza
si H = 1 MueveDisco(Fuente, Destino)

3
otro
comienza
Mueve Pila(Fuente, Paso, Destino, H - 1)
MueveDisco(Fuente, Destino)
MuevePila(Paso, Destino, Fuente, H - 1)
termina
termina

Note que aunque el tercer argumento diga Destino, en realidad lo que importa es la
posición del argumento, el primer argumento siempre será la fuente, el segundo siempre
será el destino y el tercero siempre será el medio por el cual se va a realizar la
transferencia.

Los discos se pueden representar por números, los postes como arreglos de
números de dimensión 64.

Lo único que resta definir es el procedimiento MueveDisco. En el capítulo 11


definiremos este procedimiento.

Para un programador es importante saber qué funciones ya están implementadas


en la herramienta, por ésta razón facilitamos la tabla de funciones matemáticas estándar
incluidas en Turbo Pascal.

Nombre Argumento Devuelve:


Abs( X) Real o entero Valor absoluto
ArcTan( X) Real o entero Arco Tangente
Cos( X)* Real o entero Coseno
Exp( X) Real o entero Exponencial
Frac( X) real Parte decimal
Int( X) real Parte entera
Ln( X) Real o entero Logaritmo natural
Pi ninguno Valor de Pi con 20 cifras significativas
Round ( X) Real o entero Entero más próximo
Sin( X) Real o entero Seno
Sqr ( X) Real o entero Cuadrado
Sqrt( X) Real o entero Raíz cuadrada
Trunc( X) real Parte entera

El argumento de las funciones trigonométricas siempre es en radianes.

Finalizamos este capítulo diciendo que los procedimientos, las funciones y el paso
de parámetros son elementos fundamentales para poder explotar los lenguajes de
programación a su máxima potencia, sin ellos la complejidad sería inabordable.

3
PREGUNTAS CAPITULO 9 Fecha de entrega:______________
Nombre: ________________________________________________________________
(La calificación se calcula sobre el número total de respuestas, en este caso, 11.)
1.- ¿Qué son las funciones? ________________________________________________
_______________________________________________________________________
_______________________________________________________________________
2.- ¿Qué son los procedimientos? ____________________________________________
_______________________________________________________________________
_______________________________________________________________________
3.- ¿Cuáles son las dos formas de paso de parámetros? __________________________
_______________________________________________________________________
4.- ¿Cómo es el paso de parámetros por referencia? _____________________________
_______________________________________________________________________
_______________________________________________________________________
5.- ¿Cómo es el paso de parámetros por valor? _________________________________
_______________________________________________________________________
_______________________________________________________________________
6.- ¿Cuáles son las variables globales y cuándo se deben usar? ____________________
_______________________________________________________________________
_______________________________________________________________________
7.- ¿Cuales son las variables locales y cuando se usan? __________________________
_______________________________________________________________________
_______________________________________________________________________
8.- En la siguiente figura, indique que tipo de paso de parámetros utilizaría.

Medidas
Paso de parámetros por:
___________________
Traje
Sastre
Tela
Paso de parámetros por:
___________________

3
9.- Desarrolle la función Factorial en versión no recursiva y versión recursiva, haga un
programa para probarlas.
Nota: Como el factorial crece muy rápido manéjela con el tipo de dato entero largo
(longint) el cual es un tipo de dato entero de cuatro bytes que puede almacenar enteros
de poco más de nueve cifras significativas.
10.- Desarrolle la función Potencia en versión iterativa y en versión recursiva, haga un
programa para probarlas (utilice longint como el tipo de dato de la función).

3
10.- ¿Qué es un programa?, ¿Qué es programar?, pseudocódigo,
método Páez de implementación de algoritmos iterativos, refinamientos
sucesivos y codificación.

Una vez que se han definido la mayoría de los elementos de la programación ya


podemos comenzar a usarlos para construir programas. La primera pregunta que surge
es ¿qué es un programa? De hecho la pregunta ¿qué es programar? va relacionada con
ésta. Para contestar estas preguntas daremos primero algunos antecedentes.

El concepto programar aparece cuando los científicos logran crear una máquina
capaz de ejecutar instrucciones.

En las primeras computadoras se programó en código de máquina, por lo que


hacer programas era algo que requería mucho trabajo.

El siguiente paso fueron los ensambladores, en donde se le decía a la máquina


que tenía que hacer a través de mnemónicos y el programa traducía los mnemónicos a
código de máquina ahorrando el trabajo de hacer la traducción a hexadecimal u octal.

Programar en estos lenguajes era muy problemático ya que se tenía que conocer
la arquitectura de la computadora y saber en que zonas de memoria se podían cargar los
programas y los datos, además de que el hacer programas con un alto grado de
complejidad implicaba muchas horas de trabajo tanto de elaboración como de prueba.

Más adelante aparecieron los macro-ensambladores en donde era posible reutilizar


código ya escrito sin necesidad de volverlo a escribir, aunque seguían siendo muy altas
las limitaciones.

Finalmente se desarrollaron los sistemas operativos y los lenguajes formales en


donde ya no era necesario que el programador conociera la arquitectura de la
computadora y las instrucciones del procesador, y en donde ya no se tenían que
preocupar por el manejo de la memoria, de esto se encarga el sistema operativo y de la
traducción a código de máquina el compilador.

Los primeros lenguajes que aparecieron utilizaban únicamente saltos condicionales


e incondicionales, como en el ensamblador. Los programas así obtenidos podrían ser en
exceso complicados e imposibles de depurar o de alterar, ya que los rizos podían quedar
traslapados, por lo se buscó una solución a éste problema.

El resultado fueron los lenguajes estructurados en donde se utilizan estructuras de


control para dirigir el flujo del programa.

Hay quien piensa que la programación apareció con las computadoras, pero en
realidad el concepto de programación es más antiguo.

3
Para programar lo único que se necesita es un lenguaje de especificación que no
sea ambiguo y algo que se requiera representar.

Se podría decir que los primeros programas que aparecieron en la historia fueron
las obras de teatro de los griegos, en donde a través de un lenguaje se narraba algún
acontecimiento de la historia en forma de hacer la reconstrucción de los hechos de la
suma manera en que se dieron y en donde cada personaje de la obra podría ser
interpretado por un diferente actor de tal forma que se podría decir que el guión de la obra
de teatro es también un programa. Nótese la capacidad de las obras de reconstruir
virtualmente una realidad acontecida en el pasado.

Más adelante hubo necesidad de implementar un lenguaje para representar


sonidos, compases, en sí, música. Así es como nace la notación musical a través de la
cual el músico puede representar melodías y en donde cualquier interprete
unívocamente, es decir, sin temor reproducir otra cosa, puede reproducir exactamente lo
que el autor compuso. De esta forma se puede decir que las partituras musicales son
también programas que al ejecutarse (interpretarse) reconstruyen idénticamente la
melodía que el autor compuso originalmente.

De la misma manera que en el teatro y la música, a través de un lenguaje de


especificación es posible describir aspectos de la realidad en una computadora y
reconstruirlos tantas veces como se quiera. En la computadora es posible hacer
descripciones-representaciones de la realidad. Estas descripciones-representaciones las
haremos a través del lenguaje descriptivo.

Así pues un programa es un conjunto de instrucciones que se le dan a una


computadora con el objeto de tener descripciones-representaciones en términos
computacionales de aspectos de la realidad.

Ejemplo: Supongamos que somos matemáticos y cada vez que tenemos un


sistema de ecuaciones lineales es muy laborioso encontrar la solución. Sabemos como
resolverlo y además sabemos que el procedimiento de solución es muy mecánico.
Entonces a través de un lenguaje de computación podemos hacer la descripción de como
se resuelve el sistema de ecuaciones y una vez que la descripción está hecha, cada vez
que requiramos resolver un sistema simplemente ejecutamos esa descripción (es decir,
corremos el programa) y alimentándolo con los nuevos datos resolvemos el problema.
Nos ahorraremos trabajo, ¿no?

Luego entonces, podemos decir que programar es hacer una descripción en


términos computacionales de una parte de la realidad a través de un vehículo descriptor.

Programar es más que escribir líneas de código, es transmitirle a la computadora


nuestro conocimiento de cómo resolver problemas.

La programación estructurada apareció antes que los lenguajes estructurados, así


que lo que se hacia originalmente era implementar las estructuras de control con los
elementos del lenguaje utilizado. Para programar estructuradamente fue necesario crear

3
un lenguaje universal a través del cual fuera posible programar y después traducir este
lenguaje a algún lenguaje en particular. El resultado fue el pseudocódigo.

El pseudocódigo abarca desde una versión muy burda del algoritmo hasta una
versión que no presenta problema para ser codificada, es decir, tolera secciones de
código en lenguaje natural y a través de refinamientos sucesivos se va bajando el código
de nivel semántico hasta que éste ya puede ser codificado. Utiliza sus propias estructuras
de control las cuales, de acuerdo a lo que se encontró, son suficientes y necesarias para
implementar cualquier algoritmo. Niclaus Wirth el creador de Pascal tuvo la idea de
implementar un lenguaje que manejara las estructuras de control tal como estaban
descritas en el pseudocódigo con el objeto de ahorrar esta traducción del pseudocódigo a
un lenguaje no estructurado haciendo que programar en Pascal se convirtiera
prácticamente en escribir los algoritmos en pseudocódigo.

Con el pseudocódigo, como ya se mencionó, también se puede emplear la técnica


de refinamientos sucesivos que puede ser útil cuando no se tiene la idea completa del
algoritmo.

Cabe mencionar que el pseudocódigo no es la traducción al español del programa,


el pseudocódigo es un lenguaje por derecho propio y solo tiene algunas diferencias con el
lenguaje de programación Pascal. También cabe mencionar que el lenguaje C es un
lenguaje estructurado pero aunque las estructuras de control no son idénticas a las del
pseudocódigo sí tienen su equivalencia uno a uno con él.

Por lo tanto, como ya vimos, los pasos para la elaboración de un programa son:

1) Entender el problema
2) Hacer el análisis del mismo.
3) Programar en pseudocódigo el modelo de solución propuesto.
4) Codificarlo.
5) Cargarlo en la computadora para su ejecución y ajuste.
6) Darle mantenimiento durante su tiempo de vida.

Método de Desarrollo Descendente (Top-Down)

Existe un método de desarrollo de programas muy poderosa llamada Método de


Desarrollo Descendente o De Arriba A Abajo (Top –Down). Ésta metodología consiste en
plantear desde el más alto nivel de abstracción una solución del problema en el programa
principal. No es necesario que los procedimientos que se invoquen existan, únicamente
es necesario saber que pueden desarrollarse después, es decir, que son descriptibles.

Ponemos poner el siguiente ejemplo: deseamos crear un programa que le


entregue al usuario el número de números primos que pida.

Etapa 1) Comprender bien el problema.

3
Se trata de que la computadora pregunte cuántos números primos desea el
usuario y ella encuentre los números primos hasta completar el número de números
primos que pide el usuario.

Etapa 2) Hacer el análisis del problema.

Para hacer el programa en realidad en este momento no necesitamos saber como


se encuentra el siguiente número primo, únicamente es necesario saber que es posible
invocar una función (que todavía no está creada) que me diga si un número es primo o no
y únicamente a través de contadores llenar el requisito del usuario.

Etapa 3) Programar en pseudocódigo el modelo de la solución propuesto.

Podemos utilizar la metodología Páez para la creación de algoritmos iterativos.

Esta metodología consta de los siguientes pasos:

Si el problema tiene solución iterativa:


1° En caso de ser iterativa encontrar cual es la o las instrucciones núcleo del
algoritmo.
2° Preparar variables para el siguiente ciclo.
3° Encontrar la estructura de control de flujo que las envuelve.
4° Inicializar variables.
5° Entregar resultados.
6° Declarar las variables y poner el nombre del programa, procedimiento o
función.
Si el problema tiene solución recursiva entonces
1° Encontrar el caso base
2° Desarrollar la parte recursiva del cuerpo del algoritmo

Como el problema tiene solución iterativa:

1° Encontrar cual es la instrucción núcleo o las instrucciones núcleo del algoritmo.

Las instrucciones núcleo podrían ser las siguientes:

si EsPrimo(I) entonces
comienza
Escribe(I)
NmroDPrms ← NmroDPrms + 1
termina

Observe que las instrucciones núcleo se escribes algo indentadas y en el centro de


la hoja de papel o del área de trabajo para que podamos escribir lo que va alrededor
indentando hacia la izquierda sin que nos vaya a faltar papel y así completar el programa.

2° Paso, preparar las variables para el siguiente ciclo.

3
Como no sabemos antes de comenzar el bucle cuantas iteraciones se van a
realizar las dos instrucciones que se pueden utilizar son repite y mientras, pero no el
para. Escogeremos el repite, así que necesitaremos actualizar el contador I para el
siguiente bucle quedando el algoritmo de la siguiente manera:

si EsPrimo(I) entonces
comienza
Escribe(I)
NmroDPrms ← NmroDPrms + 1
termina
I←I+1

Utilizaremos la sintaxis de Pascal en donde el símbolo ";" se utiliza únicamente


como separador de enunciados.

3° Encontrar la estructura de control de flujo que las envuelve.

Como mencionamos en el punto anterior, la estructura seleccionada será un repite,


quedando el algoritmo de la siguiente forma:

repite
comienza
si EsPrimo(I) entonces
comienza
Escribe(I)
NmroDPrms ← NmroDPrms + 1
termina
I←I+1
termina
hasta(NumroDPrmos = NmroDPrmosUsro)

4° Inicialización de variables.

En este paso se observa qué variables requieren inicialización. Hay dos formas de
inicializar una variable, una a través de un enunciado de asignación y otra a través de una
lectura. Por lo tanto el algoritmo quedará:

I←2
NmroDPrmos ← 0
Lee(NmroDPrmosUsro)
repite
comienza
si EsPrimo(I) entonces
comienza
Escribe(I)
NmroDPrms ← NmroDPrms + 1

3
termina
I←I+1
termina
hasta (NmroDPrmos = NmroDPrmosUsro)

5° Entrega de resultados.

Existen algoritmos en donde se entrega el resultado hasta el final del algoritmo y


otros como éste que al mismo tiempo que se van realizando las iteraciones se van
entregando resultados, por lo tanto éste paso ya se realizó.

6° Declaración de variables, nombre del programa, procedimiento o función.

Una vez que ya sabemos cuantas y cuales variables vamos a necesitar lo único
que hay que hacer es declarar las variables. Solo tenemos que identificar qué tipo de dato
es cada variable. Al final del algoritmo terminamos con un punto final. De tal forma que el
programa quedará de la siguiente manera:

pograma NumerosPrimos;

declaraciones
I, NmroDPrms, NmroDPrmsUsro: entero

comienza
I←2
NmroDPrmos ← 0
Lee(NmroDPrmosUsro)
repite
comienza
si EsPrimo(I) entonces
comienza
Escribe(I)
NmroDPrms ← NmroDPrms + 1
termina
I←I+1
termina
hasta(NmroDPrmos = NmroDPrmosUsro)
termina

Podemos correr en papel nuestro algoritmo para probar que funcione. Pero, como
podemos observar, nos falta definir la función EsPrimo, así que haremos este trabajo
para que nuestro algoritmo quede completo.

Para poder contestar si un número es primo o no tenemos que consultar a la


definición de ¿Qué es un número primo?

3
"Un número es primo si es un número natural que únicamente puede ser dividido
por exactamente dos número naturales, él mismo y la unidad”.

Nótese que el número 1 no es un número primo ya que sólo tiene un divisor. Se


puede decir que esta definición se puede tomar también como una especificación de lo
que es un número primo. Lamentablemente todavía no podemos alimentar a las
computadoras con especificaciones como ésta para que ellas puedan en base a la
especificación contestar preguntas o hacer el trabajo. Los lenguajes que se han
desarrollado para las computadoras no alcanzan a “comprender” todavía lo que se
conoce como lenguaje natural (lenguaje en el que esta hecha la especificación anterior) y
por lo tanto, será necesario re-escribir esta especificación para que la computadora la
pueda procesar..

Podemos cambiar la especificación para que sea más fácil representarla en


términos computacionales re-escribiéndola de la siguiente manera:

"Dado un número natural, si existe al menos un divisor entre la unidad y el número


dado, dicho número no es primo, en otro caso, sí lo es".

Para la computadora será más fácil comprender ésta especificación y ésto será
todo lo que vamos a tener que hacer, revisar si existe un divisor intermedio entre la
unidad y el número.

A todas luces éste es un algoritmo iterativo por lo que podemos utilizar de nuevo la
metodología Páez para desarrollo de algoritmos iterativos.

1° Escribir la instrucción núcleo o instrucciones núcleo, es decir, la instrucción o


instrucciones que se van a repetir muchas veces en el algoritmo pensando en una corrida
con muchas iteraciones. Como ya mencionamos, esto se hace al centro del área de
trabajo dejando un sangrado.

si N módulo I = 0 entonces
EsPrimo ← falso

Esto quiere decir que si encontramos un número cuyo residuo de dividir nuestro
número y él es cero hemos encontrado al menos un número que divide en forma exacta a
nuestro número por lo que la variable Primo tomará un valor falso. Observe también la
forma de programar con si´s ( if´s en inglés). Es posible crear otra función que se llame
divisible para hacer más clara la definición. Esta función lo único que haría es recibir dos
números y contestar “verdadero” si es que son divisibles y “falso” en caso contrario. El
operador “módulo” generalmente tiene mayor precedencia que el operador “=” por lo que
no se requieren los paréntesis.

2° Preparación de variables para el siguiente ciclo y actualización de variables.

3
Para que los bucles se realicen adecuadamente es necesario actualizar variables
al final de cada uno para que las variables estén en el número correcto en el siguiente, de
otra manera podemos generar bucles infinitos.

si N módulo I = 0 entonces
EsPrimo ← falso
I←I+1

Note que en pseudocódigo no se utilizan separadores de enunciado. En caso de


tener dos enunciados en una misma línea se separarán con “;”.

3° Escribir la estructura de control que envuelve a la instrucción núcleo.

Para seleccionar qué estructura de control es la adecuada usaremos el siguiente


criterio que se plantea en Pascal y que me parece bastante adecuado.

Si se sabe de antemano cuantos bucles se van a ejecutar usar un “para”.

Si no sabemos de antemano el número de bucles que realizará el ciclo lo más


recomendable es utilizar un repite.

Si se requiere proteger el código para que no falle en casos límite inferiores se


recomienda utilizar un mientras.

En el caso de los bucles de repeticiones indefinido es recomendable que el


programador utilice la estructura de control que le parezca más intuitiva con respecto a la
especificación que este representando.

En este utilizaremos un mientras pensando en de la siguiente manera:

repite
comienza
si N módulo I = 0 entonces
EsPrimo ← falso;
I←I+1
termina
hasta(N módulo (I – 1) = 0) o (I - 1 >= N - 1)

La prueba se hace contra I – 1 ya que ya se incremento en 1 el índice para el


siguiente ciclo si es que lo hubiera.

4° Inicialización de variables. Es necesario inicializar variables, de otra manera


puede ser que tengan basura ocasionando que nuestro algoritmo de resultados erróneos.

I←2
EsPrimo ← verdadero

3
repite
comienza
si N módulo I = 0 entonces
Primo ← falso
I←I+1
termina
hasta((N módulo (I – 1) = 0) o (I >= N – 1))

Note que no se inicializa la variable “N”, ésta se inicializará en el paso de


parámetros. Como ya mencionamos, en general todas las variables se deben inicializar,
excepto en los casos repite en que la actualización se hace al inicio dentro del bucle y por
lo menos se actualizará una vez la variable antes de llegar a una prueba de condición
como en el caso de un menú como se verá más adelante.

Si analizamos el algoritmo se comporta bien para casos mayores que 2, en el caso


de 2 el algoritmo falla ya que el intervalo entre 2 y 2 es cero, y como la comparación se
hace con respecto a N – 1 y en este caso N – 1 es 1, el intervalo queda entre 2 y 1 por lo
que sacaremos a 2 del algoritmo.

si N = 2 entonces EsPrimo ←verdadero


otro
comienza
I←2
EsPrimo ←verdadero
repite
comienza
si N módulo I = 0 entonces
Primo ← falso
I←I+1
termina
hasta((N módulo (I – 1) = 0) o (I >= N - 1))
termina

Es importante agregar algunos filtros para que el algoritmo se comporte bien con
casos especiales todo tipo de entrada posible, por lo que quedaría de la siguiente forma:

3
si((2 <= N) y (N <= MaxInt)) entonces
comienza
si N = 2 entonces EsPrimo ←verdadero
otro
comienza
I←2
EsPrimo ← verdadero
repite
comienza
si N módulo I = 0 entonces
EsPrimo ← falso
I←I+1
termina
hasta((N módulo (I – 1) = 0) o (I -1 >= N - 1))
termina
termina
otro
Primo ← falso

5° Entrega de resultados.

En general el sentido de todo algoritmo es entregar un resultado, por lo que es


necesario poner una instrucción que escriba el resultado, de otra manera no sabremos
que pasó adentro de la máquina, en este caso, el resultado de regresará en el nombre
mismo de la función, así que no haremos nada ya que al finalizar el algoritmo el resultado
quedará ya en el nombre de la función, no hay que hacer ninguna otra asignación.

Ya hemos terminado nuestro primer intento de algoritmo y ya podemos ponerle el


comienza y termina de los extremos.

3
comienza
si((2 <= N) y (N <= MaxInt)) entonces
comienza
si N = 2 entonces EsPrimo ← verdadero
otro
comienza
I←2
EsPrimo ← verdadero
repite
comienza
si N módulo I = 0 entonces
Primo ← falso
I←I+1
termina
hasta((N módulo (I – 1) = 0) o (I - 1 >= N - 1))
termina
termina
otro EsPrimo ← falso
termina

5° Declaración de variables.

Una vez que ya está terminado el algoritmo podemos declarar las variables. Esto
es mejor que primero declarar variables y luego hacer el programa, puesto que todavía no
sabemos que variables iremos a usar.

3
declaraciones
I: entero

comienza
si((2 <= N) y (N <= MaxInt)) entonces
comienza
si N = 2 entonces EsPrimo ← verdadero
otro
comienza
I←2
EsPrimo ← verdadero
repite
comienza
si N módulo I = 0 entonces
Primo ← falso
I←I+1
termina
hasta((N módulo (I – 1) = 0) o (I - 1 >= N - 1))
termina
termina
otro EsPrimo ← falso
termina

3
6° Nombre de la función

función EsPrimo(N: entero): booleano;


declaraciones
I: entero;

comienza
si((2 <= N) y (N <= MaxInt)) entonces
comienza
si N = 2 entonces EsPrimo ← verdadero
otro
comienza
I←2
EsPrimo ← verdadero
repite
comienza
si N módulo I = 0 entonces
Primo ← falso
I←I+1
termina
hasta((N módulo (I – 1) = 0) o (I - 1 >= N - 1))
termina
termina
otro EsPrimo ← falso
termina

Es importante agregar una línea donde se defina la constante MaxInt en el


programa, esta línea corresponderá al valor entero máximo que soporta la representación
entera de la herramienta. En el caso de Pascal MaxInt es igual a 32767.

También podemos agregar una línea que avise en caso de que exista un sobreflujo
en el calculo del siguiente número primo quedando los algoritmos como sigue:

3
función EsPrimo(N: entero): booleano;
declaraciones
I: entero;

comienza
si((2 <= N) y (N <= MaxInt)) entonces
comienza
si N = 2 entonces EsPrimo ← verdadero
otro
comienza
I←2
EsPrimo ← verdadero
repite
comienza
si N módulo I = 0 entonces
Primo ← falso
si I = MaxInt Escribe(‘Sobreflujo en la variable I’)
otro
I←I+1
termina
hasta((N módulo (I – 1) = 0) o (I - 1 >= N - 1))
termina
termina
otro EsPrimo ← falso
termina

3
programa NumerosPrimos
declaraciones
I, NmroDPrms, NmroDPrmsUsro: entero

comienza
I←2
NmroDPrmos ← 0
Lee(NmroDPrmosUsro)
repite
comienza
si EsPrimo(I) entonces
comienza
Escribe(I)
NmroDPrms ← NmroDPrms + 1
Termina
si I = MaxInt Escribe(‘Sobreflujo en la variable I’)
otro I ← I + 1
termina
hasta(NumroDPrmos = NmroDPrmosUsro)
termina

Etapa 4) Codificar en turbo Pascal.

Este trabajo se le deja al estudiante. En esta etapa el código fuente debe constar
con mensajes que hagan al programa amigable para el usuario.

Etapa 5) Cargarlo en la computadora para su depuración, ajuste y pruebas.

Cargarlo y depurar el programa de errores lexicográficos y sintácticos. Hacer


pruebas al programa de casos simples y límite comenzando por el ejemplo más simple
que se elaboró en la etapa 1 y/o 2 del desarrollo.

A partir de éste momento ya podemos comenzar a depurar nuestro programa. Esto


lo haremos corriendo el programa paso a paso con el depurador para ver si el programa
hace lo que nosotros queremos. La primer prueba que haremos será alimentar el
programa con el caso más simple. Comenzaremos pidiendo sólo un número primo.

Lo primero que hará la herramienta para correr el programa paso a paso será
compilar el programa. El compilador comprobará que el programa es un programa
producido por su gramática. En caso de no serlo el compilador marcará errores en los
casos en donde no pueda reconocer al programa. Si hay cosas extrañas pero salvables
únicamente enviará advertencias (warnings).

Será necesario que el programador remueva todos los errores para que el
programa pueda correr. No será lo mismo con las advertencias, es responsabilidad del
programador dejar las advertencias.

3
Generalmente los errores que marca un compilador son errores sintácticos. Estos
errores se producen cuando no se emplea el formato adecuado de las estructuras de
control. Cada estructura de control tiene una sintaxis, es decir, un formato que tiene que
ser respetado, de otra manera el compilador no la reconocerá como parte de su
gramática.

En cuanto a los refinamientos sucesivos se puede comenzar planteando el


problema a grandes rasgos aunque éste no esté a un nivel semántico que la
computadora pueda entender y poco a poco irlo bajando hasta que llegue al nivel
codificable. Éste método requiere que existan barios borradores, cada uno de menor nivel
semántico hasta tener la versión final que podrá ser codificada en un lenguaje de
programación.

Un ejemplo de este método lo encontramos en el problema de las ocho reinas que


resuelve Gillermo Levine en su libro de Introducción a la Computación y a la
Programación Estructurada en el capítulo 7 página 238. De nuevo, se pueden incluir los
refinamientos sucesivos en nuestro método si se comienza editando el programa principal
como un borrador en semilenguaje natural y poco a poco se va implementando el
algoritmo con nombres de procedimientos que aún no existen pero que se desarrollarán
más adelante.

Etapa 6) Mantenimiento del sistema, para los alcances de este curso este paso no
lo realizaremos.

3
EJERCICIOS CAPÍTULO 10 Fecha de entrega: ______________
Nombre: ________________________________________________________________
1.- Codifique el programa de los números primos, cárguelo, depúrelo y pruébelo.
2.- Escriba los programas que calculen las siguientes funciones con el error que solicite el
usuario con la siguiente condición de paro: El error del valor calculado por el programa
debe ser menor que el error solicitado por el usuario. El criterio de error puede ser el
siguiente: El error calculado puede ser el valor del último término sumado. Observe que
en las series un término es positivo y otro es negativo por lo que se debe tomar el valor
absoluto del término y por lo que el valor real debe estar a una distancia menor al último
valor sumado del último valor calculado. Ejemplo: el primer valor para la serie del seno es
x por lo que si comenzamos de cero, la incertidumbre para la primera iteración es x, es
decir el valor calculado es x ± x. En las sigientes iteraciones la incertidumbre se irá
reduciendo tanto como se reduzcan los términos. Observe que los términos se reducen
muy rápido ya que se dividen entre la función factorial y la función factorial es la que
crece más rápido. Utilice funciones para calcular las potencias y los factoriales y utilice
longint para el tipo de tato de la función factorial, ya que ésta crece muy rápido. El valor
de x está dado en radianes. 360° equivalen a 2π radianes.

Ejemplo de pregunta: ¿Calcule el valor del seno de 0.5 radianes con un error de 0.1?

Llene la siguiente tabla con sus resultados.


Grados Radianes Seno con Seno con Seno con Seno
precisión de precisión de precisión de
0.1 0.01 0.001
0 0 0.000000
30 π/6
45 π/4 0.7071
57.29 1
60 π/3
90 π/4 1.00000

3
n
sen x =  -1 (i-1) x (2 i - 1) = +x1 - x3 + x5 - ……
i=1 (2 i - 1) ! 1! 3! 5!

Grados Radianes Coseno con Coseno con Coseno con Coseno


precisión de precisión de precisión de
0.1 0.01 0.001
0 0 1.000000
30 π/6
45 π/4 0.7071
57.29 1
60 π/3
90 π/4 0.00000

n
cos x =  -1 (i-1) x (2 i - 2 ) = +1 – x2 + x4 - ……
i=1 (2 i - 2) ! 0! 2! 4!

ex =  _x (i-1) = +1 – x1 + x2 - ……
i=1
( i - 1)! 0! 1! 2!

ln ( 1 + x ) =  -1 (i - 1) x i= +x – x2 + x3 - ……
i=1
i 1! 2! 3!

3
11.- ARREGLOS, CADENAS Y REGISTROS.

Hasta ahora sólo hemos trabajado con los tipos de datos básicos, enteros, reales,
caracter y booleanos. Con todos estos datos es posible construir arreglos, cadenas y
estructuras.

ARREGLOS

Un arreglo es un conjunto de datos organizados en forma de celdas. La celda de


un arreglo se puede acceder mediante una constante o una variable llamada índice. El
índice es una variable entera por medio del la cual se puede seleccionar la celda que se
va a acceder. En Pascal y en todos los lenguajes en general los compiladores no
proporcionan los arreglos inicializados a cero, por lo que si un arreglo se va a emplear es
importante que exista una sección que inicialice todas las celdas antes de comenzar a
trabajar con el arreglo.

En Pascal un arreglo se declara de la siguiente manera:

var A: array [1..5] of integer;

en donde se declara un arreglo de enteros de tamaño 5.

En C un arreglo se declara de la siguiente manera:

int a[4];

en donde se indica que la variable a es un arreglo de cinco elementos, de 0 a 4.

En Pascal es posible declarar un arreglo de la dimensión deseada únicamente


agregando la siguiente dimensión seguida de comas dentro del paréntesis cuadrado.

Ejemplo: si se requiere declarar un arreglo de enteros de dimensión dos de tamaño


10 se hace de la siguiente manera:

var A: array [1..10, 1..10] of integer;

En C es posible declarar un arreglo de dos dimensiones de la siguiente manera:

int a[4][4];

En Pascal, si agrego subíndices puedo tener un arreglo de la dimensión que se


requiera.

Ejemplo:

A: array[1..10, 1..10, 1..10] of integer;

3
En este caso A es un arreglo de enteros de dimensión tres de tamaño 10.

En C se hace de la siguiente manera:

int a[9][9][9];

Es importante mencionar que la computadora tiene una memoria principal finita y


que si los arreglos son demasiado grandes pueden generar problemas en la ejecución del
programa, por lo que no es muy conveniente declarar arreglos exageradamente grandes.

El acceso a los elementos de los arreglos generalmente se hace a través de


índices como ya lo mencionamos. Por ejemplo, si queremos inicializar todo el arreglo con
ceros tendríamos que hacer lo siguiente:

Como sabemos de antemano cuantos ciclos vamos a ejecutar nos conviene utilizar
la estructura de control for.

for I := 1 to 10 do
for J := 1 to 10 do
A[ I, J] := 0;

En C es de la siguiente manera:

for( i = 1; i < 9; ++i)


for( j = 1 ;to I < 9; ++i)
a[ i][ j] = 0;

Con los arreglos es posible representar todo tipo de cosas que se muevan sobre
un tablero, ejemplo, damas inglesas, ajedrez, gato y también elementos matemáticos
como matrices.

Ya teniendo habiendo definido lo que es un arreglo se puede crear algoritmos que


busquen un elemento en el arreglo o que ordenen el arreglo ya sea de mayor a menor o
de menor a mayor. A tales algoritmos se les llama atgoritmos de búsqueda y
ordenamiento. Los algoritmos de ordenamiento son ejemplos muy útiles para ilustrar el
uso de arreglos.

Los algoritmos de búsqueda son muy importantes ya que sin ellos sería imposible
acceder a los datos en los grandes sistemas en tiempos prácticos. Los algoritmos de
búsqueda más simples son el algoritmo de búsqueda secuencial y el de búsqueda
binaria.

Existen varios algoritmos de ordenamiento, uno de los más famosos es el método


de la burbuja que consiste en pasar recorridos de ordenamiento de dos a la vez por todo
el arreglo hasta que el arreglo quede perfectamente ordenado. Se le llama de la burbuja

3
ya que en cada pasada el elemento mayor queda al final de la sección del arreglo que se
está ordenando, es decir, se va moviendo hacia arriba de la misma forma que lo hace una
burbuja. El inconveniente de éste algoritmo es que se realizan muchos cambios para
poder ordenar el arreglo. Es extremadamente simple en líneas de código pero no es el
más eficiente. El algoritmo es el siguiente:

for I := 1 to Limite -1 do
for J := 1 to Limite - 1 do
if A[J] > A[J +1] then
begin
Temp := A[I];
A[I] := A[I +1];
A[I+1] := Temp
end;

En C el código es el siguiente:

for(i = 0; limite –1; ++limite)


for(j = 0; limite-1; ++limite)
if (a[j] > a[j+1])
{
temp = a[i];
a[i] = a[i +1];
a[I + 1] = Temp;
};

También existen otros algoritmos de ordenamiento como el Insertion Sort,


Selección Sort, y el Shell Sort, y algoritmos recursivos como el Quick Sort y el Merge
Sort.

El Inserton Sort consiste en considerar que la lista va creciendo a partir de un


elemento y que la lista está ordenada, de tal manera que cada vez que se quiera agregar
un elemento a la lista, se sacará el elemento de la lista poniéndolo en una variable
temporal, generando ésto un hueco. Se desplazan todos los elementos de la lista
mayores a éste, de tal forma que el hueco quede en la posición donde le corresponde al
nuevo elemento y ahí será donde se inserte, de ahí el nombre de Insertion Sort. El
algoritmo termina cuando se inserta el último elemento de la lista.

En los inicios de la computación estos algoritmos de ordenamiento jugaron un


papel preponderante ya que una de las primeras habilidades que se pueden explotar en
la computadora es su capacidad de ordenar y clasificar información en forma masiva,
ésto fue tan importante que en España a las computadoras hasta la fecha se les llama
ordenadores.

3
Los primeros algoritmos de ordenamiento que se crearon fueron muy intuitivos
pero poco eficientes y poco a poco se fueron elaborando algoritmos más complejos en
base a la experiencia de los primeros.

En cuestión de ordenamiento no se puede decir que un algoritmo es


categóricamente mejor que otro, solo se puede decir que para algunos casos es mejor
uno y para otros, otro.

Aquí mostraremos de nuevo el programa de las torres de Hanoi ya que para


resolver este problema se requieren arreglos. Como recordamos el programa es el
siguiente y lo único que agregaremos es el procedimiento MueveDisco el cual es
implementado con arreglos que operan como pilas. Una pila es un arreglo visto en forma
vertical en donde el elemento con el índice menor se encuentra abajo y el elemento con
el índice mayor se encuentra arriba. La pila requiere de una variable apuntador que
apunta al elemento que se encuentra en el tope de la pila. Este índice se inicializa con 0.
Cada vez que se ingresa un elemento a la pila se incrementa primero el apuntador y
después se almacena en la celda apuntada por él la información. Cuando se extrae un
elemento de la pila se utiliza la información apuntada por el apuntador y ya que se utilizó
se decrementa el apuntador en una unidad. Como se requieren tres pilas se requieren
tres apuntadores. Estos apuntadores son variables de tipo entero.

programa Hanoi
comienza
MuevePila(A, C, B, ApA, ApC, ApB, H)
termina

Donde el poste de la izquierda se representa por A, el de en medio por B y el


derecho por C, ApA, ApC, ApB son apuntadores que indican el tope de las pilas A, B, C.

procedimiento MuevePila(var Fuente, Destino, Paso: arreglo; var ApA, ApC, ApB: entero
H: entero)
comienza
si H = 1 MueveDisco(Fuente, Destino, ApF, ApD)
otro
comienza
Mueve Pila(Fuente, Paso, Destino, ApF, ApP, ApD, H - 1)
MueveDisco(Fuente, Destino, ApF, ApD)
MuevePila(Paso, Destino, Fuente, ApP, ApD, ApF, H - 1)
termina
termina

Mueve Disco(var Fuente, Destino, ApF, ApD: arreglo)


comienza
ApD ← ApD + 1;
Destino[ApD] ← Fuente[ApF];
Fuente[ApF] ← 0;
ApF ← ApF – 1

3
termina

La inicialización del programa se deja al estudiante.

CADENAS

En Pascal al tipo de dato cadena se le llama string, en realidad es un arreglo de


caracteres unidimensional del tamaño que el usuario requiera.

Pero ¿por qué son necesarias las cadenas de caracteres? En realidad una variable
caracter no nos serviría de mucho ya que generalmente el lenguaje se escribe por medio
de cadenas de caracteres, éste texto por ejemplo está compuesto de cadenas de
caracteres. El caso más común de cadenas de caracteres es una lista de nombres.
También, gracias a las cadenas se pueden escribir los programas para computadora.

En Pascal es posible manejar cadenas como si fueran números, es decir, se


pueden utilizar los operadores relacionales entre dos cadenas como se hace con
variables numéricas. No es necesario utilizar funciones especiales para comparar
cadenas. Por ejemplo es posible saber por medio de un relacional qué cadena va
después de otra en orden ascendente.

También es posible manipular los caracteres de una cadena individualmente de tal


forma que se pueden crear juegos como el ahorcado en donde el usuario tiene que
adivinar la cadena oculta únicamente proporcionando en cada tirada un caracter. Si el
caracter se encuentra en la cadena éste y su o sus posiciones en la cadena se irán
revelando al usuario a través de la pantalla. También es posible representar cadenas de
moléculas por medio de cadenas y buscar ciertas secuencias.

La forma de declarar una cadena en Pascal es:

Nombre: string [20];

La forma de referirse a un elemento de la cadena Nombre es:

WriteLn( Nombre[1]);

Esta instrucción imprimirá el primer caracter de la variable Nombre.

También es posible copiar cadenas. La forma de hacerlo es la siguiente:

Nombre1 := Nombre2;

En fin, las cadenas de caracteres juegan un papel fundamental en la


programación.

3
Las cadenas en C se manejan como arreglos de caracteres. El tipo string no existe
en C por lo que se hace mediante definir un arreglo tipo char. Existe una librería que
contiene funciones para manejar cadenas.

REGISTROS

Un registro es una estructura de datos que puede estar formada de datos de la


misma naturaleza como por ejemplo vectores, en donde cada vector puede tener dos o
más coordenadas o de diferente naturaleza como los registros de clientes de una base de
datos bancaria que contienen cadenas, enteros y datos tipo moneda. Este tipo de dato es
útil cuando se requiere guardar información conformada con datos que tienen un valor útil
siempre y cuando estén juntos.

Los datos de una persona están formados por tipos de datos de diferente
naturaleza, por ejemplo el nombre y la dirección son cadenas mientras que la edad es un
entero. A cada uno de los elementos de un registro se le llama campo.

Generalmente en las bases de datos la información se almacena con éstos tipos


de datos, es decir con registros, por lo que es importante tocarlos en este capítulo.

Mencionamos anteriormente la enorme capacidad de la computadora de buscar en


grandes volúmenes de información de manera muy rápida. Esta capacidad se explota
principalmente en lo que se conocen como Bases de Datos. Una Base de Datos es un
conjunto de archivos que almacenan información que está relacionada entre si de una
organización, empresa, sección gubernamental, etc. En nuestro caso utilizaremos bases
de datos de un solo archivo. Éste archivo lo iremos llenando con registros. Cuando
necesitemos consultar nuestra base de datos consultaremos los registros para recuperar
la información deseada.

En este capítulo no construiremos la base de datos, por el momento lo único que


nos interesa es que el estudiante se familiarice con este tipo de dato.

Para declarar en Pascal un tipo de dato registro se hace lo siguiente:

type

persona =
record
Nombre: string[30];
Direccion: string[40];
Telefono: string[10]
end;

var
Empleado: persona;

Para referirse a los campos de una variable registro se hace lo siguiente:

3
ReadLn( [Link]);

Es decir, se hace poniendo el nombre del registro seguido de un punto seguido del
nombre del campo que queremos manipular.

Pascal proporciona una manera de evitar reescribir varias veces el nombre del
registro con el que se va a trabajar. Esto se hace por medio de la proposición with. La
sintaxis es la siguiente:

with identificador de registro do


proposición

3
Ejemplo:

with Empleado do
begin
WriteLn( Nombre);
WriteLn( Direccion);
WriteLn( Telefono);
end

3
EJERCICIOS CAPÍTULO 11 Fecha de entrega: ______________
Nombre: ________________________________________________________________
1.- Suponga que tiene una caja con cinco casilleros numerado del 1 al 5 y cinco bolas de
pull de billar, es decir, bolas numeradas, no necesariamente seguidas. ¿Sería usted
capaz de ordenar las bolas en orden ascendente? Escriba el algoritmo que usted utiliza
en pseudocódigo utilizando el método de diseño descendente que ordene las bolas en
orden ascendente.
(Tip: analice que es lo que usted hace para ordenarlas y escríbalo en términos
computacionales, si esto no ayuda escriba lo que usted hace en lenguaje natural paso a
paso y luego escríbalo en términos computacionales, identifique lo que se hace
iterativamente)
2.- Codifique el algoritmo.
3.- Cárgelo y pruébelo.
4.- Sustituya el 5 por una constante Const Limite = 5 al inicio y sustituya todos los 5 por
Limite y corra el algoritmo.
5.- Ahora cambie Límite por 10 y vea que funciona el programa. Escriba que utilidad tiene
hacer esto.
6.- Optimice el algoritmo anterior.
7.- Cambie el algoritmo para que trabaje con cadenas.
8.- Haga un programa para ordenar por medio del método de la burbuja.
9.- Haga un programa para ordenar por medio del método insertion sort. Imagine que se
encuentra jugando cartas. Piense qué es lo que hace un jugador para ordenar sus cartas.
Se toma la primera como referencia. Se comienza con la segunda. Si es menor que la
primera se recorre la primera y se inserta la segunda, si no se deja en su posición. Luego
se toma la tercera y se le busca posición que puede ser antes de la primera, entre la
primera y la segunda o después de la segunda y se inserta. Esto se hace hasta que la
última carta ha sido insertada en su posición, de aquí su nombre de insertion sort
algorithm.
10.- Escriba un programa que despliegue el cuadro mágico de la dimensión que quiera el
usuario. El cuadro mágico es un cuadro en el que todas sus columnas y todos sus
renglones suman lo mismo. El cuadro mágico lo puede elaborar con arreglos de tamaño
impar. En la casilla del centro pone el número 1, el siguiente número lo pondrá arriba a la

3
derecha siempre y cuando la celda no esté ocupada. Si la celda ya está ocupada lo
pondrá abajo de la casilla en turno. Si se sale del cuadro al hacer el cálculo del siguiente
lugar reentre por el lado contrario, es decir, si se sale por arriba, reentre por abajo, si se
sale por el lado derecho, reentre por el lado izquierdo hasta colocar el último número.
Después de hacer esto la suma cada una de las columnas y de cada uno de los
renglones dará el mismo número.
11.- Escriba un programa que sume matrices.
12.- Escriba un programa que multiplique matrices.
13.- Escriba un programa en donde se declare una arreglo de 10 registros, en donde el
registro se llame Persona y en donde tenga los siguientes campos: Nombre: cadena 30,
Dirección: cadena de 40, Edad, entero, Teléfono: cadena de 15, Celular: cadena de 15,
Correo electrónico: cadena de 25 y Página web: cadena de 20. Se lean los campos del
registro y se escriban. El programa debe presentar un menú en donde haya un
procedimiento para ingresar un registro, otro para editar un registro y otro para desplegar
todo el arreglo.

3
12.- MODO GRÁFICO.

Las interfaces hombre máquina han ido cambiando y evolucionado conforme a ido
pasando el tiempo. En un principio la comunicación con la computadora era mediante
tarjetas perforadas. Después se hizo interactiva a través de monitores y finalmente se
convirtió en gráfica haciendo uso de iconos y botones.

El modo gráfico ofrece una alternativa más colorida de comunicación con el


usuario.

Es posible pintar líneas, círculos y hasta hacer animación en la pantalla.

La graficación en modo gráfico se hace a través de pixeles. Un pixel (picture


element) es un punto de la pantalla. Es posible ordenarle a la computadora pintar un pixel
del color que nosotros queramos en cualquier punto de la pantalla.

Generalmente la pantalla es una matriz de 479 por 639 pixeles. El pixel (1,1) es el
pixel que se encuentra en la parte superior izquierda de la pantalla y el pixel (639, 479) se
encuentra en la parte inferior derecha de la pantalla.

Debido a que las coordenadas en el eje Y crecen de arriba hacia abajo es


necesario hacer una inversión y un desplazamiento en caso de querer hacer graficación
de una línea recta.

Lo primero que tenemos que hacer para manejar el modo gráfico es declarar en el
uses la librería Graph, esto se hace mediante la siguiente instrucción:

uses Graph;

Después declarar las variables GraphDriver y GraphMode como tipo entero:

var GraphDriver, GraphMode: integer;

Posteriormente inicializar GraphDriver con la función Detect;

GraphDriver := Detect;

Finalmente inicializar el modo gráfico con la instrucción InitGraph, su sintaxis es la


siguiente:

InitGraph (GraphDriver, GraphMode, PathToDriver);

Donde GraphDriver es el argumento que indica el manejador de video que se


desea emplear y GraphMode es la constante que indica el modo gráfico deseado.
PathToDriver es la ruta donde se encuentra el archivo el manejador de la interfase gráfica

3
que en la actualidad utilizando un monitor SuperVGA es [Link]. Este archivo
generalmente se encuentra en la ruta C:\TP\BGI\.

El procedimiento Detect detecta por nosotros cual es el manejador de video que


más conviene utilizar y hace que GraphMode sea el modo de más alta resolución posible.
Generalmente el manejador más utilizado que Detect envía como resultado es el
[Link].

Ejemplo:

InitGraph (GraphDriver, GraphMode, 'C:\TP\BGI\');

En la versión 7.0 de Turbo Pascal para Windows a veces presenta algunos


problemas cuando se corre el modo gráfico y estos problemas dependen de la máquina y
del sistema operativo que esté corriendo ya que Turbo Pascal fue originalmente diseñado
para correr bajo MS-DOS.

Por ejemplo en Windows Milenium y Windows 2000 al agregar el FDelay sí corren


los programas pero no puede ejecutarlos paso a paso, reporta que no encuentra un
archivo fuente en TP\SURCE\[Link], así que se puede crear archivo con ese
nombre y ponerlo en éste directorio y correr sus programas paso a paso.

Como se pudo observar para inicializar el modo gráfico en el procedimiento


InitGraph uno de los argumentos es el manejador de la interfase gráfica (GraphDriver). El
manejador es un programa que se encarga de manejar el periférico en cuestión, en éste
caso la interfase gráfica (el monitor) y al que el programa le envía comandos gráficos
para que éste a su vez los traduzca al código del periférico. Éste manejador es diferente
para cada tipo de monitor. Conforme han ido evolucionando los monitores desde blanco y
negro y resoluciones bajas hasta los monitores de color y de alta resolución que hoy
conocemos se han ido desarrollando los diferentes manejadores. El tipo de monitor más
común que se maneja actualmente es el SuperVGA por lo que el manejador más utilizado
es el [Link] que soporta este monitor. Lo primero que hace el procedimiento es
buscar el manejador en el directorio donde se encuentra el programa, pero si no lo
encuentra lo busca en la ruta de acceso (path) que se da como el tercer argumento en
InitGraph y si no lo encuentra ahí el programa marcará un error.

Pero si se requiere que el programa corra independientemente en un disco flexible


será necesario agregar el manejador al disco.

Para saber cuales son los valores máximos de X y Y se utilizan las siguientes funciones:

GetMaxX;

GetMaxY;

3
Los colores disponibles son los siguientes:

Black (0) Negro


Blue (1) Azul
Green (2) Verde
Cyan (3) Azul Cianuro
Red (4) Rojo
Magenta (5) Magenta
Brown (6) Café
LightGray (7) Gris Claro
DarkGray (8) Gris Oscuro
Light Blue (9) Azul Brillante
LightGreen (10) Verde Brillante
LightCyan (11) Cyan Brillante
Light Red (12) Rojo Claro
Light Magenta (13) Magenta Claro
Yellow (14) Amarillo
White (15) Blanco

INSTRUCCIONES GRÁFICAS

SetColor (Color) Establece el color a utilizar en los procedimientos.

SetBkColor (Color) Establece el color del fondo.

PutPixel (X, Y, Color) Pinta un pixel en la pantalla.

MoveTo (X,Y) Mueve el cursor a estas coordenadas.

MovRel (X, Y) Mueve el cursor X, Y unidades del actual.

Line (X1, Y1, X2, Y2) Pinta una línea de las coordenadas iniciales a las
finales.

LineTo (X2, Y2) Pinta una línea de las coordenadas actuales a las
indicadas.

SetLineStyle (LineStyle) Establece el tipo de línea a pintar.

Rectangle (X1, Y1, X2, Y2) Pinta un rectángulo en la pantalla entre las
esquinas dadas.

Circle (X, Y, Radius) Pinta un circulo de radio R con centro en X, Y.

Ellipse (X, Y, StAngle, EndAngle, XRadius, YRadius) Pinta una elipse en las
coordenadas X, Y en el ángulo de inicio, con ángulo de terminación, con radio en X
XRadius y con radio en Y en YRadious.

3
Arc (X,Y, StAngle, EndAngle, Radius) Pinta un arco en X, Y con ángulo de inicio
StAngle, ángulo de terminación EndAngle y radio Radius.

Sector (X, Y, XRadius, YRadius, StAngle, EndAngle) Pinta un sector con centro
X,Y, radio en X XRadius y radio en Y YRadius, ángulo de inicio StAngle y ángulo de
terminación EndAngle.

PieSlice (X, Y, StAngle, EndAngle, Radius) Pinta un sector similar al anterior pero
relleno.

COLOREAR Y RELLENAR

Los patrones del tipo de rellenado son los siguientes

EmptyFill (sólido, con el color del fondo)

SolidFill (sólido, con el color especificado)

LineFill (se rellena con guiones)

LtSlashFill (se rellena con ///)

SlashFill (se rellena con /// gruesas)

LtBkSlashFill (se rellena con ///)

BkSlashFill (se rellena con \\\ gruesas)

HatchFill (se rellena con un ligero sombreado)

XHatchFill (se rellena con un sombreado denso)

InterLeaveFill (intercala líneas)

WideDotFill (se rellena con puntos muy dispersos)

CloseDotFill (se rellena con puntos distribuidos densamente)

UserFill (patrón de rellenado definido por el usuario)

INSTRUCCIONES PARA EL COLOREADO Y RELLENADO

SetFillStyle (FillType, Color) establece el tipo de rellenado y el color.

FloodFill (X, Y, Color) rellena una región determinada por un punto de la región y el
color de la frontera.

3
TEXTO EN UNA PANTALLA GRÁFICA

SetTextStyle (Font:Word; Direction: word; CharSize: word);

Es para seleccionar el tipo de imprenta y el tamaño para los caracteres.

El parámetro Font puede ser uno de los siguientes:

DefaultFont

TriplexFont

SmallFont

SansSeriFont

GothicFont

La primera opción se refiere al tipo de letra basado en los bits, el resto


corresponden a tipos de letra con un trazo particular.

El parámetro Direction puede tomar uno de los siguientes valores:

HorizDir

VerDir

El parámetro CharSize tiene un valor definido por omisión de 1 para el tipo de letra
con base en los bits y 4 para tipos de letra con cierto trazo. Se pueden elegir otros valores
para tamaños mayores de tipos.

SetTextJustify (Horiz, Vert: word);

Establece la forma en que se debe colocar el caracter en relación con el pixel. De


manera horizontal el pixel puede estar en la esquina izquierda, el centro o la esquina
derecha del caracter, mientras que verticalmente el pixel puede estar en la esquina
superior, al centro o en la esquina inferior del caracter.

Las opciones de Horiz son:

LeftText (alineado a la izquierda)

CenterText (centrado)

RightText (alineado a la derecha)

3
Las opciones para Vert son:

BottomText (abajo)

CenterText (centrado)

TopText (arriba)

OutText ('String'); Envía la cadena a la posición donde esté el apuntador activo.

OutTextXY (X1, Y1, 'String'); Envía la cadena a la posición indicada con


coordenadas en modo gráfico.

ALMACENAMIENTO Y RECUPERACIÓN DE IMÁGENES

ImageSize (X1, Y1, X2, Y2): integer;

Esta función regresa el número de bytes necesarios para almacenar la imagen en


el rectángulo indicado en los parámetros en el modo gráfico activo.

GetImage (X1, Y1, X2, Y2, Variable);

Este procedimiento almacena el rectángulo indicado en la variable de tipo arreglo.

PutImage (X1, Y1, Variable, CopyPut)

Esta instrucción copia el rectángulo en las coordenadas indicadas tomado de la


variable indicada. El último parámetro índica la forma de ser copiada. CopyPut indica que
la imagen se copiará sorbe los pixeles existentes.

EL PUERTO DE VISUALIZACIÓN Y RECORTE

SetViewPort (X1, Y1, X2, Y2: integer; Clip: boolean);

Es para exhibir gráficas en una porción rectangular de la pantalla. El parámetro


Clip determina si las operaciones de dibujo son recortadas en las fronteras del puerto de
visualización. Clip puede tomar los valores de ClipOn o ClipOff. El puerto de visualización
definido por omisión está en las coordenadas (0, 0, GetMaxX, GetMaxY) sin recorte. Esta
instrucción también se usa en los juegos cuando se quiere actualizar solo una parte de la
pantalla.

ClearViewPort;

Es para eliminar el puerto de visualización activo y mover el apuntador activo a (0,


0).

3
SONIDO

Write (Chr (7));

Es para emitir un bip por la bocina.

El llamado a procedimiento Sound (n) emite un sonido de frecuencia n.

El llamado a procedimiento NoSound corta el sonido que se este emitiendo.

Para calcular frecuencias de las notas musicales se usa la siguiente función


exponencial:

f (n) = F Exp (K n)

donde:

n es el número de la nota
F es la frecuencia de la nota cero
K es una constante

Por convención "la" de la quinta octava tiene una frecuencia de 440 Hz, así que F =
440. En la música occidental una octava se divide en 12 semitonos:

do do# re re# mi fa fa# sol sol# la la# si

La escala tiene 8 octavas, un incremento de una octava equivale a multiplicar por


dos la frecuencia, o sea:

f (n + 12) = 2 f (n)

Exp (k (n + 12)) = 2 Exp (K n)


Exp (K n) * Exp (12 K) = 2 Exp (K n)
por lo tanto:
K = ln (2) / 12

La música occidental usa intervalos de 1/16, 1/8, 1/4, 1/2, 1, 2, y 4 tiempos. No hay
una definición de cuanto es un tiempo, y puede ser muy corto en un arreglo "molto
vivace", regular en un "andante" y muy largo en un "adagio".

LECTURA Y ESCRITURA DE DATOS

La lectura y desplegado de datos tienen su problemática cuando se trabaja en


modo gráfico. Por ejemplo si no se agrega la librería Crt, el modo gráfico puede correr sin
FDelay y de esta forma se pueden hacer Read's y Write's, inclusive Write's conteniendo
variables, el problema es que no se pueden utilizar todos los procedimientos que están

3
contenidos en la librería Crt como lo son ClrScr, GoToXY, ReadKey y KeyPressed,
además de que si se termina la pantalla al hacer scrolls la gráfica se irá corriendo hacia
arriba por lo que habrá que dar un ClearViewPort.

Cuando se declara la biblioteca Crt ya se pueden utilizar los comandos citados


anteriormente, el problema es que los Write's ya no serán ejecutados. Por lo que no será
posible desplegar ninguna variable pero si se podrán hacer lectura de datos en cualquier
parte de la pantalla o directamente utilizando el procedimiento ReadKey.

Cuando se utilizan Read's hay que tener cuidado donde se encuentra el cursor
antes de leer ya que el número tecleado aparecerá en la pantalla en formato ASCII y
alterará lo que se encuentre desplegado.

También puede hacer la lectura de los datos en modo ASCII antes de que entre al
modo gráfico si es que el problema requiere datos para graficar. Inclusive puede salir de
modo gráfico y regresar a modo ASCII después, o puede estar pasando de modo ASCII a
modo Gráfico y viceversa intermitentemente si así lo desea.

Como comentábamos anteriormente, lamentablemente la interface gráfica de


Pascal no cuenta con procedimientos para escribir variables en la pantalla por lo que solo
se podrá escribir texto predefinido. Utilice el procedimiento MovTo(X, Y) para posicionar
el cursor de modo gráfico en el lugar donde Ud. requiera el texto y luego escriba el texto
con el procedimiento OutText('string'), ejemplo:

MoveTo(50, 50);
OutText('Dame el valor de X. ');
ReadLn(X);

PARA CERRAR EL MODO GRÁFICO O REGRESAR AL MODO ESTÁNDAR

Finalmente para salir del modo gráfico hay que cerrarlo, esto se hace con la
instrucción:

CloseGraph;

Finalizamos el capítulo diciendo que las interfaces más vistosas y amigables son
las interfases en modo gráfico por lo que se han convertido en un estandar para crear las
interfases hombre máquina. Es importante resaltar que la información presentada en
modo gráfico es más agradable a la vista que la información presentada en una pantalla
en modo ASCII (también llamado modo texto).

Se puede agregar que la parte de graficación ha sido fundamental para desarrollar


el concepto de realidad virtual y forma una parte fundamental en la síntesis de imágenes
artificiales siendo esta explotada por las empresas que se dedican a los juegos
electrónicos. Cabe agregar que no es la única aplicación que se le puede dar al modo
gráfico, los físicos las utilizan mucho para sus modelos, los ingenieros en las diferentes
disciplinas para simulación y cálculo ya que un diseño tridimensional es mas ilustrativo

3
que ver únicamente números, y no se diga de los matemáticos, que trabajan en topología
y gráficas de cuerpos en tres dimensiones. En fin, los campos de aplicación son muchos
y es importante hacer notar que este campo no solo es desarrollado por las compañías
de juegos electrónicos.

3
3
EJERCICIOS CAPÍTULO 12 Fecha de entrega: ______________
Nombre: ________________________________________________________________
1.- En una hoja de papel cuadriculada dibuje un carrito coloreado de perfil con figuras
geométricas.
2.- Haga un programa que dibuje ese carrito en pantalla.
3.- Haga que el carrito se mueva a la derecha y a la izquierda de la pantalla hasta que el
usuario pulse una tecla.
4.- Dibuje un escenario.

3
3
13.- ARCHIVOS

El manejo de archivos juega un papel muy importante en la programación. En


ocasiones existen programas que únicamente alimentarlos requiere una gran cantidad de
tiempo y si se comete un error al introducir un dato se tiene que repetir todo el proceso.
También existen programas en los que no es fácil desplegar en pantalla el resultado de
su proceso por ser éste muy extenso, así que es mejor escribirlo en un archivo para
poderlo examinar con detenimiento. En otros programas la salida puede ser la entrada de
otro. Finalmente también existen programas que manejan tal cantidad de datos que no
sería suficiente la memoria principal para manejarlos. La solución a todos estos
problemas nos la proporcionan los archivos.

Un archivo es una colección de datos. Existen archivos que se acceden


secuencialmente y archivos indexados los cuales es posible acceden en una forma
semisecuencial. El acceso secuencial tiene sus ventajas así como sus desventajas. Una
ventaja es que su estructura es muy simple, la desventaja es que para acceder un dato
tenemos que recorrer todo el archivo hasta encontrar el dato. Para grandes bases de
datos los archivos secuenciales son inoperantes.

De ésta forma es posible hacer un programa que lea los datos de un archivo y
también es posible hacer un programa que mande los resultados a un archivo, del mismo
modo es posible que lea los datos de un archivo y escriba los resultados en otro y hasta
es posible que actualice los datos de uno o varios archivos.

La forma de hacer esto varía de acuerdo a los diferentes lenguajes, pero la esencia
es la misma.

En Pascal lo primero que tenemos que hacer es declarar que tipo de dato va a
conformar nuestro archivo. Los archivos pueden contener enteros, reales, caracteres,
registros y arreglos, en general cualquier tipo de dato estándar o definido por el usuario.
Por lo tanto en el área para declarar las variables globales se declarará también el tipo de
archivo con el que vamos a trabajar.

Si lo que vamos a almacenar en él son datos tipo registro entonces declaramos:

type
alumno = record
Nombre: string[30];
Carrera: string[35];
Telefono: string[15];
end;

archivo = file of alumno;

var
Alumno1, Alumno2: alumno;

3
F: archivo;

En donde F es un identificador de archivo.

Lo segundo que tenemos que hacer para manejar un archivo en Pascal es


asignarle al identificador un nombre de un archivo. La sintaxis de la instrucción para hacer
esto es:

Assign(IdDArch, 'NombreDelArchivo. extención');

ejemplo:

Assign(F, '[Link]');

Después de asignarle un nombre de archivo al identificador de archivo es


necesario reinicializar el archivo. Todo archivo contiene índices que apuntan al último
elemento que se acceso. Para acceder al primer elemento es necesario reinicializar el
archivo. Esto se hace con la instrucción Reset( IdDArch). Es recomendable antes de
reinicializar un archivo desactivar los mensajes de error de entrada/salida con el objeto de
evitar que se pare el programa en caso de que el archivo no haya sido creado aún. El
código sería el siguiente:

{$I-}
Reset (F);
{$I+}

Posteriormente hacer la siguiente pregunta:

if IOResult <> 0 then


ReWrite(F);

IOResult es una variable del compilador a través de la cual es posible saber si hubo un
error de entrada/salida, por eso no es necesario declararla. Así como ésta, existen varias
que solo se utilizan en caso necesario.

La instrucción ReWrite(IdDArch) crea un archivo nuevo con el nombre que se le


asignó al identificador con la instrucción de asignación o borra el ya existente en caso de
que éste no haya sido creado dejándolo vacío. Generalmente esta instrucción solo se
ejecuta la primera vez cuando el archivo no ha sido creado. Es posible crear un archivo
vacío con el editor de Turbo Pascal, pero esto es más complicado para un principiante.

Una vez que el archivo ya está asignado e inicializado ya podemos trabajar con él
haciendo lecturas y/o escrituras.

Para escribir en el archivo únicamente se debe poner el identificador de archivo


antes de la lista de variables a escribir en el llamado a procedimiento Write. La sintaxis es
la siguiente:

3
Write(IdentificadorDArchivo, Lista de variables);

ejemplo:

Write(F, Alumno1);

La sintaxis de la instrucción de lectura para un archivo es la siguiente:

Read(IdentificadorDArchivo, Lista de variables);

ejemplo:

Read(F, Alumno1);

Al finalizar de usar el archivo es necesario cerrarlo. Mientras un archivo esté en


uso no podrá ser abierto por otro programa. La sintaxis de la instrucción para cerrar un
archivo es:

Close(IdentificadorDArchivo);

ejemplo:

Close(F);

Para leer el archivo hasta el final se utiliza la función EoF( IdentificadorDArchivo) la


cual es verdadera cuando se ha llegado al final del archivo.

Un bucle que lee un archivo hasta el final sería:

while not EoF(F) do


Read(F, Alumno1);

El while se utiliza para proteger al programa en caso de que el archivo esté vacío y
no se pueda hacer ni siquiera una lectura.

En los programas en donde se almacenan registros en un archivo solo es


necesario tener dos registros como variables. Para buscar un registro en el archivo, en un
registro se almacena el dato que se requiere buscar y en el otro la información leída del
archivo, se comparan y si son iguales se detiene la búsqueda puesto que ya se ha
encontrado la información buscada.

Esta forma de manejar archivos en Pascal es útil, pero tiene la desventaja de no


poder almacenar datos de diferentes tipos en un solo archivo y en algunos casos esto es
una limitación muy grande de Pascal. Sin embargo el manejo de registros en Pascal es
bastante simple.

3
Otro procedimiento que es muy útil en el manejo de archivos es el comando:

Seek(IdDe Archivo, localidad)

Este procedimiento ubica el apuntador de archivo en el registro indicado por


localidad, ejemplo:

Seek(F, 5)

Posicionará el apuntador de archivo en el registro 5 de tal manera que el siguiente


Read o Write se hará sobre el registro indicado.

Otra función útil es FileSize(IdDeArchivo). Esta función regresa el tamaño del


archivo. Puede ser útil para agregar registros al final del archivo editando el siguiente
código:

Seek(F, FileSize(F))

Esta línea posiciona el apuntador de archivo al final de éste, de tal forma que si se
requiere anexar registros solo es necesario ejecutar posteriormente una escritura.
FileSize regresa un entero que es mayor por uno al de la última componente. A esta
operación compuesta se conoce como append.

3
EJERCICIOS DEL CAPÍTULO 13 Fecha de entrega: ______________
Nombre: ________________________________________________________________
1.- ¿Qué es un archivo? ____________________________________________________
2.- ¿Cuantos tipos de acceso archivos existen? _________________________________
3.- ¿Cuando es necesario emplear archivos en un programa? ______________________
_______________________________________________________________________
4.- Diseñe un programa que funcione como un directorio telefónico.
5.- Altere el programa para que funcione como un diccionario.

3
3
14.- MÉTODOS DE DESCOMPOSICIÓN, DESARROLLO DESCENDENTE (TOP-
DOWN) Y PROGRAMACIÓN MODULAR.

El método de desarrollo descendente es un excelente método para desarrollar los


programas, sobre todo programas grandes y con un alto nivel de complejidad. Este
método nos garantiza que por muy grande y compleja que sea nuestra solución jamás
perderemos el control del proyecto además de poder entregar resultados en un tiempo
finito y de buena calidad.

A grandes rasgos el método de desarrollo descendente consiste en programar el


programa principal de tal modo que tenga la mayor carga semántica y que muestre el
algoritmo solución global de tal forma que en el programa principal muestre los
subprogramas o sub-problemas a resolver. La estrategia principal de este método es
"divide y vencerás". El algoritmo se repite con estos subprogramas hasta que ya no se
puedan descomponer más. La estructura que formarán el programa principal y los
procedimientos será una estructura arbolada. Cuando se termina de programar el último
procedimiento ya estamos listos para codificar el programa.

En detalle el método de diseño descendente consiste en:

1° Plantear el problema en lenguaje natural (es decir, en el lenguaje en el que hablamos).


Esto puede servir al mismo tiempo como los comentarios del encabezado del programa
para indicar que hace el programa iniciando con la frase "Este programa calcula...." por
ejemplo.

2° Esbozar el algoritmo a grandes rasgos con estructuras de control. Para esto se pueden
nombrar procedimientos o funciones que aún no se hayan definido (éstas se definirán
después y serán de menor nivel).

Se usarán funciones en las condiciones para dirigir el flujo del programa de la


siguiente manera, ejemplo:

si EsPrimo(N) entonces

Lo que quiere decir en lenguaje natural:

si N es primo entonces

3° Se tomará el primer procedimiento o función que aparezca en el programa principal y


se repetirá recursivamente el mismo proceso que empleamos para el programa principal
desarrollando todos los procedimientos y funciones que se necesiten para que este corra.
Este procedimiento tendrá menor carga semántica que el programa principal es decir,
tendrá menos relación con el problema que estamos resolviendo y tendrá más relación
con instrucciones en el lenguaje de programación y menos llamadas a procedimientos.

4° Esto se repetirá sucesivamente hasta que no quede ningún procedimiento y función sin
definir. Se pueden usar funciones estándar del lenguaje.

3
Cuando se terminen de codificar todos los procedimientos y funciones tendremos
la primera versión de nuestro programa.

El siguiente paso será cargarlo. Para cargarlo he irlo probado simultáneamente


podemos utilizar el siguiente método.

Cargar el programa principal y poner todas las invocaciones a procedimientos


dentro de "WriteLn" para que el programa no entre en los procedimientos. Si aparecen
funciones definirlas. De esta forma el programa principal estará corriendo aunque los
procedimientos no estén definidos aún.

Posteriormente cargar el primer procedimiento con todos los procedimientos que


cuelguen de el y probar que al correr el programa esa parte funcione bien.

Luego hacer lo mismo con los procedimientos restantes hasta que ya no haya
ningún procedimiento en el programa principal que no esté cargado.

Procederémos a la depuración y pruebas.

Una vez hechas las pruebas ya podemos generar el ejecutable. Está será nuestra
versión 1.0 de nuestro programa y deberemos hacer una copia de seguridad por
cualquier cosa que suceda. Lo peor que le puede pasar a un programador en no tener
nada que entregar. Las siguientes versiones serán optimizaciones y ampliaciones de
nuestro programa.

Pondremos un ejemplo de desarrollo del método de desarrollo descendente.

Problema: Hacer un programa que maneje un directorio telefónico. El programa debe ser
capaz de dar de alta un nuevo nombre, consultar o actualizar los datos de una persona.

El programa principal sería el siguiente:

program Directorio;

var Opcion: char

begin
repeat
begin
Opcion := ReadKey;
case Opcion of:
'a': WriteLn('Altas');
'c': WriteLn('Consultas);
'e': WriteLn('Edicion');
's': WriteLn('Salir')

3
else
WriteLn('opción inválida)
end;
end
until Opcion = 's';
end.

Este sería el bosquejo del programa principal. Podríamos correr el programa para
revisar el flujo y ver que funciona. Este uso del case es una forma muy práctica para
navegar dentro del programa. Observe como no es necesario tener los procedimientos
definidos para que el programa corra.

El siguiente paso es cargar el procedimiento Altas. Repetimos la misma estrategia.


Como en este procedimiento lo que se va a hacer es pedirle los datos al usuario y
escribirlos en el archivo eso es lo que se hará.

uses Crt;

const
N = 30;
C = 20;
T = 10;

type
alumno = record
Nombre: string [N];
Carrera: String [C];
Telefono: string [T];
end;

var
Opción: char;
Alumno1: alumno;
F: archivo;

procedure Altas
{ Este procedimiento lee los datos en un registro y los escribe en un archivo.}
begin

with Alumno1 do
begin
ReadLn (Nombre);
ReadLn (Carrera);
ReadLn (Telefono);
end
Assign (F, '[Link]');
{$I-}

3
Reset (F);
{$I+}
if IOResult <> 0 then
ReWrite (F);
Write (F, Alumno1);
Close (F);
end; { Altas}

Una vez terminado este procedimiento se procede a quitar el WriteLn


correspondiente a Altas y a probar y depurar el procedimiento.

Después se carga el siguiente procedimiento, en este caso "Consultas" y se define


y se sigue el mismo procedimiento que con "Altas".

Esto se hace con todos los procedimientos que aparecen en el programa principal
y una vez que se desarrolla el último procedimiento el programa ya puede correr
completo por primera vez. Revisamos que haga lo que queremos y entonces ya tenemos
nuestra versión 1.0.

Finalmente como tip de programación le recomendamos que al estar desarrollando


un programa, si aún no sabe como se comportan algunos procedimientos o tipos de datos
en el lenguaje haga un programa para hacer algunas pruebas para adquirir éste
conocimiento y posteriormente utilice lo aprendido en el diseño de su programa, o sea, no
espere hasta que se necesite este conocimiento para hacer las pruebas ya que ésto le
consumirá más tiempo.

3
EJERCICIOS CAPÍTULO 14 Fecha de entrega: ______________
Nombre: ________________________________________________________________
1.- Explique en que consiste el método de desarrollo descendente: __________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
_______________________________________________________________________
2.- Desarrolle los procedimientos de Consultas, Edición y Listado del programa Directorio
mostrado en el capítulo.
3.- Desarrolle el siguiente problema utilizando el método de desarrollo descendente. Se
requiere colocar en un tablero de ajedrez ocho damas que no se ataquen. Haga un
programa que encuentre todas las soluciones.
Tips: Llene el tablero de arriba a abajo y de izquierda a derecha. Se sabe si una reina
ataca a otra en una diagonal si sus coordenadas suman lo mismo (diagonal que sube) o
restan lo mismo (diagonal que baja). No es necesario revisar hacia atrás ya que si se
puso una nueva reina ya se revisó que las anteriores no se atacan entre si. Utilice back
track cuando se llegue a una solución sin salida. El back track consiste en mover la reina
anterior en una posición si es que se llegó a un estado en donde no se pueden colocar
más reinas. El retroceso se hace recursivamente hasta que se llegue a un estado de no
bloqueo. El programa termina cuando la primera reina ya recorrió todas las posiciones y
la siguiente posición estaría fuera del tablero.

3
3
APÉNDICE A

REGLAS DE INDENTADO

Otro aspecto a considerar para la escritura de los algoritmos estructurados es el


indentado. El indentado es el sangrado que se le da a la parte interna de una estructura
de control para indicar pertenencia. Todo aquello que se encuentre indentado dentro de
una estructura de control indicará la pertenencia.

Se recomienda indentar con dos espacios o un tabulador los metaparéntesis


después de una estructura de control.

Se recomienda indentar todas las sentencias dentro de una estructura de control


cuatro espacios o dos tabuladores.

Si sólo es una sentencia indentar sólo dos espacios o un tabulador.

Indentar dentro de una estructura de control y desindentar cuando esta termine.

Cada metaparéntesis debe terminar en la misma columna que en la que abrió su


correspondiente metaparéntesis.

El programa debe terminar en la misma columna en que abrió su correspondiente


metaparéntesis.

Generalmente los metaparéntesis de inicio y final de programa no se indentan.

En ocasiones se puede escribir el primer metaparentesis a continuación del inicio


de la estructura de control para ahorrar un renglón y cuando se quiere que los
procedimientos largos queden en una sola hoja.

3
3
BIBLIOGRAFÍA

1. Levine Gutierrez Guillermo, Intoducción a la Computación y a la Programación


Estructurada, 2ª Ed. McGraw Hill, 1989
2. Peter Gorgono, Programción en Pascal, Ed. Addison Wesley, 1984.
3. Luis Joyanes Aguilar, Turbo Pascal, Ed. McGraw Hill.
4. Larry Joel Goldstein, Turbo Pascal, Ed. Prentice Hall.
5. Julien Henifeld, Turbo Pascal con Aplicaciones, Grupo Editorial Iberoamérica, 2ª
Ed., 1992.
6. Luis Joyanes Aguilar, Luis Rodriguez Baenay Luis Rodriguez Azuela, Matilde
Fernandez Azuela, Fundamentos de Programación, De McGraw Hill.
7. Glen Brookshear, Introducción a las Ciencias de la Computación, Addison Wesley,
4a Edición, 1995.
8. Gullermo Levine Gutierrez, Computación y Programación Moderna, Ed. Addison
Wesley, 2001.
9. Brian W Kernighan y Dennis M. Ritchie, El Lenguaje de programación C, 2ª Ed.,
Editorial Pearson Educación.
10. Swedan Fathi, Turbo Pascal 7: Referencia Rápida, Addison Wesley
Iberoamericana, 1994.
11. Haiduk H. Paul, Turbo Pascal Orientado a Objetos, Ed. McGraw Hill, 1994.

También podría gustarte