La Ciencia de Programar
La Ciencia de Programar
La Ciencia de Programar
programar
Indice general I
Indice de figuras IX
1. Introduccion 1
1.1. Lenguaje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1. Lexico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.2. Sintaxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.3. Semantica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2. Lenguajes de Programacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Logica Matematica 5
2.1. Logica Proposicional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.1. El lenguaje de la logica proposicional . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.2. Precedencia de conectivos logicos . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.3. Interpretaciones y clasificacion de las formulas logicas . . . . . . . . . . . . 9
2.1.3.1. Tautologas, contradicciones y contingencias . . . . . . . . . . . . 10
2.1.3.2. Tablas de verdad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.4. Leyes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.4.1. Equivalencias Logicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.4.2. Implicaciones Logicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
I
II INDICE GENERAL
3. Teora de conjuntos 21
3.1. Conceptos basicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.1.1. Conjunto y elemento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.1.2. Especificacion de Conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.1.2.1. Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.1.2.2. Comprension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.1.3. El conjunto vaco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.1.4. Representacion de conjuntos mediante diagramas de Venn . . . . . . . . 23
3.1.4.1. Diagramas de Venn para 2 conjuntos . . . . . . . . . . . . . . . . . 24
3.1.4.2. Diagramas de Venn para 3 conjuntos . . . . . . . . . . . . . . . . . 24
3.1.5. Contenencia e igualdad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.1.6. Conjunto universal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.2. Construccion de conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.2.1. Union . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.2.2. Interseccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.2.3. Complemento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.2.4. Conjunto de partes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.5. Producto cartesiano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.6. Producto cartesiano generalizado . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.2.7. Cardinalidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5. Relaciones y funciones 63
5.1. Relaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.1.1. Propiedades de las relaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5.1.2. Relaciones de orden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5.1.3. Relaciones de equivalencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.2. Funcion parcial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.2.1. Propiedades de las funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.3. Extension de una funcion parcial a una funcion total . . . . . . . . . . . . . . . . . . 71
5.4. Funciones importantes en computacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
5.5. Composicion de funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
5.5.1. Evaluacion como composicion de funciones . . . . . . . . . . . . . . . . . . . . 79
5.6. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.3.1. El condicional if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
6.3.2. El operador condicional ?: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
6.3.3. El condicional if sin la sentencia else . . . . . . . . . . . . . . . . . . . . . . . 93
6.3.4. Estructuras if enlazadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
6.3.5. La estructura de conmutacion (switch) . . . . . . . . . . . . . . . . . . . . . 97
6.4. Validacion de datos usando condicionales . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
6.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Bibliografa 219
Indice de tablas
VII
VIII INDICE DE TABLAS
Indice de figuras
1.1. Lenguaje
Un lenguaje es un conjunto de elementos que permite expresarnos y comunicarnos con
otros entes, ya sean personas, animales, computadores, etc. Un lenguaje esta definido por
tres elementos, el lexico, la sintaxis y la semantica.
1.1.1. Lexico
1.1.2. Sintaxis
1.1.3. Semantica
CODIGO ARGUMENTO(S)
0010 00011010
1010 10111000
0110 11010001
MNEMONICO ARGUMENTO(S)
ADD R1, F4
MOV F4, C2
SUB AX, AX
MOV AX, 18D
SUB AX, 18D
Pero con certeza el enunciado debe poseer algun valor fijo que lo califique.
El lindo y hermoso perro de Mara Antonieta; El ronroneo de los gatos. (no son
afirmaciones que puedan valorarse)
Manana llovera (hay incertidumbre acerca del valor que califica el enunciado, no
tiene una calificacion fija y precisa)
En la logica proposicional, el lexico esta definido por tres elementos: los smbolos o
letras proposicionales, los conectivos logicos y los parentesis.
Definicion. El lexico de la logica proposicional se compone de tres tipos de lexemas:
conectivos logicos: , , , ,
smbolos auxiliares: (, )
El smbolo proposicional (que se lee bottom) es usado para representar una propo-
sicion generica que su significado es siempre falso 1 , mientras que (que se lee top) es
usado para representar una proposicion generica que su significado es siempre verdadero 2 .
Las letras proposicionales p, q, r, s, t, p0 , p1 , . . . son usadas para representar proposicio-
nes, por lo tanto el significado de una letra proposicional es el significado que tiene la
proposicion que dicha letra representa.
Los conectivos logicos son operadores logicos que permiten formar frases que se llaman
proposiciones compuestas o formulas logicas a partir de smbolos y/o letras proposiciona-
les.
En la definicion mas comun de la logica proposicional clasica, estos operadores son:
El significado que cada uno de estos conectivos le da a las proposiciones compuestas que
se construyen con ellos se explicara mas adelante3 .
Los parentesis son usados para agrupar de manera apropiada las formulas o proposi-
ciones compuestas de la logica proposicional.
En la logica proposicional la gramatica se describe en terminos de formulas bien for-
madas (fbf) de manera recursiva4 , es decir, suponiendo que los smbolos y letras proposi-
cionales son fbfs y definiendo nuevas fbfs en terminos de fbfs ya construidas.
Definicion. La gramatica de la logica proposicional se define recursivamente en terminos
de formulas bien formadas (fbf), as:
iii) Si f1 y f2 son fbfs entonces: (f1 f2 ), (f1 f2 ), (f1 f2 ) y (f1 f2 ) son fbfs.
Ejemplo. Las siguientes secuencias de smbolos son formulas bien formadas:
f1 : (p (q)) (r s) f2 : (r q) (q s)
f1 : ( p)(r s) f2 : ( p q) (q p )
() () (p)
V F significado de la proposicion p
(f ) (f )
V F
F V
f : (p) q (r q) ()
para hallar el significado de f , primero se debe hallar el valor de verdad de los parentesis
mas internos y luego con esos resultados ir hallando el valor de verdad de las formulas mas
internas que vayan apareciendo, de esta manera
(r q) () (p) q (r q) ()
V F
(p) q (r q) ()
V
as, (f ) = V .
2.1. LOGICA PROPOSICIONAL 9
Uno de las principales limitaciones de las formulas bien formadas es el uso excesivo de
los parentesis, los cuales, en muchos casos, son redundantes. Para evitar este uso excesivo
de parentesis (sin que esto implique que toda formula pueda ser escrita sin parentesis), a
los conectores logicos se les asigna una prioridad que determina de manera exacta el orden
en que los parentesis se deben asumir si no se escriben. Entre mas alta es la prioridad de
un conector, los parentesis asociados a el, tienen mayor prelacion, es decir, en el proceso
de completar los parentesis, los parentesis asociados al operador con mas prioridad son
adicionados primero que los parentesis de un conectivo con menor prioridad. Las priori-
dades asignadas a los operadores se pueden observar el la tabla 2.1. Cuando en la formula
aparece el mismo operador varias veces y no se puede determinar a cual se le deben asignar
los parentesis primero, se asignan los parentesis de izquierda a derecha.
i) p q r (s p)
ii) p q r (s p) ( prioridad 3)
iv) (p q) r (s p) ( prioridad 4)
1. f = p q q p
2. f = p p
3. f = p (q r)
Solucion.
1. Si f = p q q p entonces f = {p, q}
p q pq qp pq qp
V V V V V
V F V V V
F V V V V
F F F F V
entonces f es tautologa.
2. Si f = p p entonces f = {p}
2.1. LOGICA PROPOSICIONAL 11
p p p p
V F F
F V F
entonces f es contradiccion.
3. Si f = p (q r) entonces f = {p, q, r}
p q r qr p (q r)
V V V V V
V V F V V
V F V V V
V F F F F
F V V V F
F V F V F
F F V V F
F F F F F
entonces f es contingencia.
2.1.4. Leyes
En la logica proposicional clasica, una ley logica es una equivalencia o implicacion entre
formulas logicas. Tal equivalencia o implicacion logica debe ser verdadera para cualquier
interpretacion de las letras proposicionales que conforman las formulas relacionadas por
la equivalencia (debe ser tautologa). Las mas famosas leyes logicas son: Modus Ponen,
Modus Tollen, Inconsistencia, Doble negacion, Conmutatividad, Distributivas, Asociativas
y De Morgan.
( ) ( )
V V V F F F F V
V F F V F V V V
F V F V V F V V
F F F V V V V V
Equivalencia Nombre
Tercio excludo
Contradiccion
Identidad
Dominacion
Idempotencia
Doble negacion
Conmutativas
( ) ( )
( ) ( )
Asociativas
( ) ( ) ( )
( ) ( ) ( )
Distributivas
( )
( )
De Morgan
( ) ( )
V V F V F F V
V F V F F F V
F V F V F V V
F F V V V V V
Las implicaciones logicas mas conocidas se presentan en la tabla 2.3. Se deja al lector
la demostracion de las mismas.
Implicacion Nombre
{, } ( ) Combinacion
{, } Ley de simplificacion
{, } Variante de la ley de simplificacion
{} ( ) Ley de adicion
{ } ( ) Variante de la adicion
{, } Modus ponens tambien llamado Modus ponendo
ponens (en latn, modo que afirmando afirma)
{ , } Modus tollens tambien llamado contrareciproca
modus tollendo tollens (en latn, modo que negan-
do niega)
{ , } ( ) Silogismo hipotetico
{, } Silogismo disyuntivo tambien llamado modus to-
llendo ponens (en latn, modo que negando afirma)
{ , } Variante de silogsmo disyuntivo
{ , } Ley de casos
{ } ( ) Eliminacion de equivalencia
{ } ( ) Variante de eliminacion de equivalencia
{ , } ( ) Introduccion de la equivalencia
{, } Ley de inconsistencia
Tabla 2.3. Implicaciones logicas.
el complemento puede cambiar (la pelota roja y blanca, la pelota azul y verde) de acuerdo
a una realidad. Esto da como resultado frases del estilo x juega con y.
x e y son objetos que estan relacionados mediante un predicado y dependiendo de
los objetos, se obtiene una proposicion que es V o es F . En terminos de los sujetos y
los complementos se define un predicado como una frase que dice algo acerca del sujeto
que lo relaciona con el complemento. En el ejemplo anterior el predicado es juega con
y se escribira simbolicamente mediante le expresion juegaCon(x, y), que se interpreta
conceptualmente como x juega con y.
Un predicado da una forma mas amplia de hablar. Se podra tener una coleccion
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, y sobre esta coleccion se puede definir un predicado. Por ejem-
plo, se podra hablar del predicado esP ar(x). Si se toma el predicado y se asigna al sujeto
x el valor 3 entonces esP ar(3) tendra un valor de verdad F , si se toma el predicado y se
asigna al sujeto x el valor 6 entonces esP ar(6) tendra un valor de verdad V .
A una coleccion de objetos a los cuales se les desea aplicar el predicado se le llama el
universo de discurso. Cuando en un predicado se reemplaza una variable x por un valor
concreto del universo del discurso, se dice que se esta instanciando la variable x, la
formula resultante se dice que es una instancia del predicado inicial.
Cuando no ha instanciado un predicado, a este no se le puede asignar un valor de verdad.
Por ejemplo, el predicado esP rimo(x) no se puede valorar, por el contrario, cuando se
instancian todas la variables de un predicado, lo que se obtiene es una proposicion, y por
lo tanto se cumple la condicion de que en ese caso la instancia tendra un valor o V o F ,
y no puede tener los dos a la vez.
2.2.1. Cuantificadores
Pueden haber predicados como esDigito(x) que para todos los objetos del univer-
so del discurso {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} son V . Para este mismo universo, el predica-
do esM ayora10(x) es F para todos los elementos de dicha coleccion, y el predicado
esM oduloAditivo(x) es V solo para x = 0 y para el resto de los casos sera F .
Cuando se desea expresar que un predicado P (x) describe una propiedad sobre todos
los elementos del universo del discurso o para solo algunos, se dice que se esta cuantificando
la variable x.
Cuando se desea expresar que un predicado describe una propiedad para todos los
elementos del universo del discurso, se dice que se esta cuantificando universalmente.
Cuando el predicado describe una propiedad para algunos de los elementos del universo
del discurso, se dice que se esta cuantificando existencialmente.
Para expresar estas nuevas propiedades se necesitan nuevos smbolos, y estos son los
smbolos y que permiten ampliar el lexico y se utilizan de la siguiente manera:
xP (x)
que se lee para todo x P (x).
Cuando en una expresion una variable esta cuantificada universalmente, se tiene que
Ejemplo. Si se tienen los numeros dgitos como universo de discurso y se establece como
predicado
P (x) = x es multiplo de 4,
se tiene que xP (x) = V y xP (x) = F ; esto porque el predicado sera cierto cuando
se instancia la variable con los valores 0, 4 y 8 P (0), P (4), P (8), aqu se ha tomado la
definicion de multiplo como
xP (x) xP (x): no existe un x que cumpla el predicado P quiere decir que para
todo x no se cumple el predicado P .
xHumano(x) M ortal(x)
Humano(Aristoteles)
M ortal(Aristoteles)
Cuando un profesor revisa un programa, este evalua que para toda entrada dada, se
tenga una salida esperada. Si el profesor encuentra un caso para el que el programa no
muestra una salida esperada (particularizacion universal), se concluye que el programa
no funciona pues se espera que haga lo que debe hacer para todos los posibles casos
contemplados.
La logica de predicados ayuda a establecer precondiciones en la elaboracion de los
programas. Validaciones de este tipo incluyen verificaciones en los tipos de datos, por
ejemplo:
2.3. Ejercicios
1. De los siguientes enunciados cuales son proposiciones y cuales no?, justifique su
respuesta.
Tom Hanks ha ganado dos premios Oscar como mejor actor por dos anos con-
secutivos.
Dame una cerveza.
Colombia gano ocho medallas olmpicas en Londres 2012.
Todo numero primo es impar.
1 + 1 = 2.
La diferencia de dos primos.
Todo numero par mayor que 2 puede escribirse como suma de dos numeros
primos. (Christian Goldbach, 1742).
Que hora es?.
xn + y n = z n .
x + y = z + y si x = z.
2. De las siguientes secuencias de smbolos cuales son formulas bien formadas y cuales
no?.
((p) r) (p q)
((p) (q)) (q r)
(p q) (q p)
(p p) (p p) (p (p))
3. Escriba la formula bien formada que representa cada una de la siguientes secuencias
de smbolos:
pq rsq
pqqp
p q r (q r) q
p (q r) p q (p q)
8. Con los operadores logicos y es posible expresar los otros operadores logicos
(, , ) de forma equivalente, de la siguiente manera
p q (p q)
p q (p q)
p q (p q) (q p)
9. Con los operadores logicos y es posible expresar los otros operadores logicos
(, , ). Encontrar formulas logicas que contengan solo los operadores logicos y
que sean equivalentes a las formulas pq, p q, p q y verifique que efectivamente
son logicamente equivalentes.
10. Adicional a los conectivos logicos presentados, existen otros conectivos, tal como el
conectivo o exclusivo (), el cual es muy utilizado en computacion, y tiene como
objetivo que dadas dos formulas f1 y f2 , la operacion f1 f2 sera unicamente ver-
dadera cuando se cumpla que solo una de la formulas f1 o f2 sea verdadera. De esta
manera, la semantica para este conectivo es la siguiente
11. Adicional a los conectivos logicos presentados, existe otro conectivo, tal como el
conectivo barra de Sheer (), para el cual su semantica es la siguiente
f f f
f1 f2 (f1 f1 ) (f2 f2 )
f1 f2 (f1 f2 ) (f1 f2 )
f1 f2 f1 (f2 f2 )
12. Adicional a los conectivos logicos presentados, existe otro conectivo, tal como el
conectivo flecha de Peirce (), para el cual su semantica es la siguiente
f f f
f1 f2 (f1 f2 ) (f1 f2 )
f1 f2 (f1 f1 ) (f2 f2 )
f1 f2 (f1 f1 ) f2 (f1 f1 ) f2
13. Hallar el valor de verdad para los siguientes predicados donde las variables estan
cuantificadas y el universo del discurso de las variables x y y son los numeros reales
y el de las variables n y m son los numeros naturales.
i. x n (x > n).
ii. x n (x < n).
iii. n x (x > n).
iv. n x (x < n).
v. x (x2 > 0).
20 CAPITULO 2. LOGICA MATEMATICA
14. Usando las leyes de De Morgan para cuantificadores, negar los predicados del nume-
ral 13.
Captulo 3
Teora de conjuntos
Un conjunto A es una coleccion bien definida de objetos. Se dice que una coleccion A
esta bien definida si existe un predicado A (llamado constructor del conjunto A), que
determina de manera exacta los objetos que pertenecen a la coleccion.
V, si x = 1, x = 2, x = 3 o x = 4;
(x) =
A
F, en otro caso.
(x, A) A (x)
3.1.2.1. Extension
A = {x1 , x2 , . . . , xn }
donde xi son los objetos en el conjunto A. De esta manera el predicado asociado al conjunto
es,
V, si x = xi para algun i = 1, 2, . . . , n;
A (x) =
F, en otro caso.
Ejemplos.
1. A = {1, 2, 3, 4}
2. B = {, , , }
3. C = {a, e, i, o, u}
4. B = {V, F }
5. N = {0, 1, 2, 3, 4, 5, . . .}
6. P = {1, 2, 3, 4, 5, . . .}
7. Z = {. . . , 3, 2, 1, 0, 1, 2, 3, . . .}
3.1.2.2. Comprension
Si se presenta explcitamente el predicado que define el conjunto, se dice que se esta es-
pecificando el conjunto por comprension. Esto se hace mediante la siguiente notacion:
A = x A (x).
Ejemplos.
3.1. CONCEPTOS BASICOS 23
2N = x (x = 2n) (n N)
2N + 1 = x (x = 2n + 1) (n N)
Q = x (x = pq) (p, q Z) (q 0)
I = {x x es un numero irracional}
R = {x x es un numero real}
R+ = x (x R) (x > 0)
R = x (x R) (x < 0)
R0,+ = x (x R) (x 0) 1
C = x (x = a + bi) (a, b R) (i = 1)
(i denota la unidad imaginaria)
A = x (x R) (x2 1)
Todo conjunto finito no vaco se puede representar mediante los llamados diagramas de
Venn, de la siguiente forma
1
En el contexto del calculo o el analisis matematico se usa la notacion R para este mismo conjunto,
pero en el contexto de la computacion, esta notacion se utiliza para definir el conjunto de todos los arreglos
de tipo real que se estudiaran en el captulo 11.3.2.
24 CAPITULO 3. TEORIA DE CONJUNTOS
A
1
2 3
A = {1, 2, 3, 4, 8, , , _} 4 8
_
A B
7 2 1
4
8 3
_
A B
4 s
2 3 6 7
5 n
1 l 8 u
9 0
C
3.1. CONCEPTOS BASICOS 25
Sean A y B dos conjuntos, A esta contenido en B si y solo si todos los elementos del
conjunto A estan en el conjunto B. La contenencia entre conjuntos es un predicado que
se define de la siguiente manera
contenido(A, B) (x A x B)
C B
0 8 1
2
3
4
6 _
(A = B) ( A B ).
AB
26 CAPITULO 3. TEORIA DE CONJUNTOS
BA
por lo tanto A = B
AC
C A
es decir A C
3.2.1. Union
AB (x) x (A B) = (x A) (x B)
A B = x (x A) (x B).
1. A B = B A. (conmutatividad)
3.2. CONSTRUCCION DE CONJUNTOS 27
A B A B
AB
2. (A B) C = A (B C). (asociatividad)
Ejemplo. A = {2, 4, 8, , }, B = {1, 2, 3, 4, , , _}
A B
2 3 4
1 8
_
3.2.2. Interseccion
AB (x) x (A B) = (x A) (x B)
A B = x (x A) (x B).
1. A B = B A. (conmutatividad)
2. (A B) C = A (B C). (asociatividad)
Ejemplo. A = {2, 4, 8, , }, B = {1, 2, 3, 4, , , _}
28 CAPITULO 3. TEORIA DE CONJUNTOS
A B A B
AB
A B
2
4
3.2.3. Complemento
(x) x A = (x B) (x A)
B
B
A
A = x (x B) (x A).
B
B
En la figura 3.6 se muestra una representacion grafica de la operacion A entre con-
juntos.
A B A B
B
A
B
Figura 3.6. Representacion del conjunto A mediante diagramas de Venn.
B = {8}.
A
3.2. CONSTRUCCION DE CONJUNTOS 29
A B
1
A B
B
Cuando B es un universo para A, el conjunto A es llamado complemento de A y es
notado A.
U U
A A
B
Cuando B es un universo para A, el conjunto A es llamado complemento de A y es
notado A.
1. A A = U.
30 CAPITULO 3. TEORIA DE CONJUNTOS
2. A A = .
3. (A B) = A B.
4. (A B) = A B.
U
1 3 5 6 7
9
0
A
_
(A) = {X X A}.
Ejemplo. Para el conjunto A = {1, 2, 3} se tiene que
(A) = , {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}.
Para todo par de objetos a y b existe un unico objeto c, llamado pareja ordenada de a
con b y notado c = (a, b), para el cual:
V, si x = c y = a;
1. 1 (x, y) =
F, en otro caso.
3.2. CONSTRUCCION DE CONJUNTOS 31
V, si x = c y = b;
2. 2 (x, y) =
F, en otro caso.
Los objetos (a, b) y (b, a) no son iguales cuando a b, ya que, 1 (a, b), a = V y
1 (b, a), a = F .
El conjunto producto cartesiano de dos conjuntos A y B, es el conjunto de todas las
parejas ordenadas, cuya primer componente es un elemento del conjunto A y cuya segunda
componente es un elemento del conjunto B. El conjunto producto cartesiano es unico y
se nota A B. El conjunto producto cartesiano puede ser definido mediante el siguiente
predicado
AB (x, y) (x, y) A B = (x A) (y B)
A B = (x, y) (x A) (y B).
A1 A2 An = (a1 , a2 , . . . , an ) (ai Ai ), i = 1, 2, 3, . . . , n.
3.2.7. Cardinalidad
Todos los conjuntos poseen una propiedad muy importante llamada cardinalidad, esta
se refiere a la cantidad de elementos que posee el conjunto. El cardinal de un conjunto A
es unico y se denota por A.
Con base en el concepto de cardinal se puede decidir si un conjunto es finito o infinito,
as, un conjunto es finito si el conjunto es el vaco o su cardinal es un numero natural, en
caso contrario se dice que es infinito.
A= F = {, , , }
B = {0} G = {1, 3, 5, 7, 9, , }
C = {_} H = {2, 4, 6, 8, 0, , }
D = {} I = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, , , , , _}
E = , {}
se tiene que:
A = 0 D = 1 G = 7
B = 1 E = 2 H = 7
C = 1 F = 4 I = 15
Para el caso de los conjuntos infinitos, estos pueden tener distinto cardinal,
Ejemplo.
N = 0 N N = 0
(N) = 1 = 20
(que se lee alef cero)
P = 0
I = 1 = 20
2N = 0
2N + 1 = 0 R = 1 = 20
Z = 0 R R = 1 = 20
Q = 0 C = 1 = 20
3.3. Ejercicios
1. Sea A el siguiente predicado constructor del conjunto A
V, si x es un dgito y x es un multiplo de 3;
A (x) =
F, en otro caso.
Cual es el conjunto listado por extension que define A (x)?.
3. Encuentre todos los conjuntos A, tales que A B, para el conjunto B = {l, n, s, u}.
i. A B vii. B C
ii. A C
B
viii. A
iii. (A B) C ix. A
iv. (A C) (B C)
BC
x. A
v. B C xi. A B
C
vi. A C
C
B
xii. A
i. A B v. B C ix. B A C
ii. B A vi. C B x. B C A
iii. A C vii. A B C xi. C A B
iv. C A viii. A C B xii. C B A
A B = A + B A B,
esto porque al sumar A y B se incluye dos veces A B, y por lo tanto hay que
restarlo. Para el caso de tres conjuntos A, B y C, Cual es el cardinal del conjunto
A B C?. Ayuda: Utilice diagramas de Venn para tres conjuntos.
i. A B iii. B A v. C A
ii. A C iv. B C vi. C B
i. A B iii. B A v. C A
ii. A C iv. B C vi. C B
i
x
suma
sumando1
sumando2
Edad
paisDeNacimiento
_nombre
area_circulo
Las siguientes secuencias de caracteres son ejemplos de secuencias que no son identifi-
cadores, por que?:
1er_mes
primer nombre
while
p@dre
da
sirven para declarar entidades (variable, funciones, etc.) que son diferentes, pues al ser la
misma palabra, difiere en que algunas letras son mayusculas en unos identificadores y en
los otros no.
Una variable es un espacio de la memoria M donde se almacena un dato, es un espa-
cio donde se guarda la informacion necesaria para realizar las acciones que ejecutan los
programas.
1 1 0 1
al nombre, este simplemente debe ser un identificador valido que no sea una palabra
reservada.
En general una variable con identificador x se declara as
T x;
Estos tipos de datos son conocidos como primitivos pues estan definidos en el lenguaje
de programacion C++ y porque de ellos se pueden derivar otros tipos de datos definidos
por el programador.
4.2.1. Enteros
int x;
lo que sirve para declarar que la variable x pertenece a los enteros que son representables
en el lenguaje C++.
El subconjunto de los numeros enteros que pueden ser representados en el lenguaje
C++, es el conjunto de enteros con signo que se representan con 32 bits (4 bytes) y que
38 CAPITULO 4. INTRODUCCION A LOS LENGUAJES DE PROGRAMACION
usan un tipo de codificacion interna llamada complemento a 2, los valores de este conjunto
varan en el rango
2147483648 x 2147483647
Los literales enteros, es decir, la sintaxis de los valores que pueden ser asignados a las
variables de tipo int que soporta C++ son por ejemplo:
-32768 -0 -1 -127
32768 0 1 127
+32768 +0 +1 +127
Cuando se declara una variable de tipo entero, no se sabe que valor tiene, por eso es
necesario inicializar la variable. Los siguientes son ejemplos de inicializaciones de variables
de tipo int
int i = 0;
int j = 1;
int n = 5;
int p = -10;
int k = -1;
4.2.2. Reales
double x;
lo que sirve para declarar que la variable x pertenece a los reales de maquina que son
representables en el lenguaje C++.
El subconjunto de los numeros reales que pueden ser representados en el lenguaje C++,
es un subconjunto propio de los racionales, que se representan con 64 bits (8 bytes) y que
usan un tipo de codificacion definida por el IEEE standard for Binary Floating-Point
Arithmetic 754 de 1985, los valores distintos de 0 de este conjunto varan en el rango
y
2.2250738585072014 10308 x 1.7976931348623157 10+308
que dan una precision cientfica de 15 dgitos.
4.2. TIPOS DE DATOS PRIMITIVOS 39
Los literales reales, es decir, la sintaxis de los valores que pueden ser asignados a las
variables de tipo double que soporta C++ son por ejemplo:
Cuando se declara una variable de tipo real, no se sabe que valor tiene, por eso es
necesario inicializar la variable. Los siguientes son ejemplos de inicializaciones de variables
de tipo double
double e = 2.7182818284;
double a = +1.0;
double X = -1.0;
double Luz = 2.998e+8;
double const0 = 1.3806488E-23;
double coordenada_1 = -2.5;
4.2.3. Booleanos
bool x;
lo que sirve para declarar que la variable x pertenece al conjunto de los booleanos B =
{V, F }.
Como solo hay dos valores de verdad V y F , en C++ solo hay dos literales para
representar los valores logicos, estos son:
true false
bool b = true;
bool flag = true;
bool exp = false;
bool isPrime = false;
40 CAPITULO 4. INTRODUCCION A LOS LENGUAJES DE PROGRAMACION
Ejemplo. Para las inicializaciones del ejemplo anterior se tiene que las siguientes expre-
siones son equivalentes
bool b = 1;
bool flag = 1;
bool exp = 0;
bool isPrime = 0;
4.2.4. Caracteres
Los caracteres representan los smbolos definidos por el conjunto ASCII (American
Standard Code for Information Interchange). Los caracteres se representan con 8 bits (1
byte), lo que ofrece 256 smbolos distintos. El conjunto ASCII cumple con la siguiente
caracterstica
char x;
lo que sirve para declarar que la variable x pertenece al conjunto de los ASCII.
Existen algunos caracteres especiales que no tiene su propio smbolo en el teclado o
que no se imprime el smbolo en la pantalla o que tienen un uso particular en C++
(son reservados) y que son utilizados comunmente; estos caracteres se representan de la
siguiente manera, usando el smbolo \ (back slash) como smbolo auxiliar:
\n : Nueva lnea.
\t : Tabulador horizontal.
\ : Imprime apostrofo.
\v : Tabulador vertical (coloca el cursor justo debajo del ultimo caracter de la lnea actual).
Cuando se declara una variable de tipo caracter, no se sabe que valor tiene, por eso es
necesario inicializar la variable. Los siguientes son ejemplos de inicializaciones de variables
de tipo char, para indicar que se esta definiendo un literal de caracter, se encierra el
smbolo entre
apostrofos , as como se muestra a continuacion:
char c = ;
char CH = \n;
char letra = a;
char caracter = A;
char value = \";
char _last = \;
char C_0 = &;
char cero = 0;
Para los datos de tipo numerico se pueden utilizar los siguientes operadores infijos, a
excepcion del operador - que puede actuar tambien como un operador prefijo:
+ : Suma de dos valores, por ejemplo, cuando se evalua la expresion 2.0 + 3.0 se obtiene
el valor 5.0.
- : Resta de dos valores, por ejemplo, cuando se evalua la expresion 2.0 - 3.0 se obtiene
el valor 1.0. Tambien se utiliza para cambiar el signo de un numero si se utiliza con
un solo operando, por ejemplo, cuando se evalua la expresion -23 se obtiene el valor
23.
* : Multiplicacion de dos valores, por ejemplo, cuando se evalua la expresion 2.0 * -3.0
se obtiene el valor 6.0. La multiplicacion es explicita, es decir no se puede escribir
una expresion como (2.0)(-3.0), esto se debe escribir como (2.0)*(-3.0).
/ : Division de dos valores, cuando alguno de los operandos es real retorna la division
exacta, por ejemplo, cuando se evalua la expresion -3.0/2 se obtiene el valor 1.5.
Cuando ambos operandos son enteros, se obtiene la parte entera de la division exacta,
por ejemplo, cuando se evalua la expresion -3/2 se obtiene el valor 1. El valor del
segundo operando debe ser distinto de 0.
% : El resto de la division de dos numeros que deben ser enteros, representa la operacion
matematica
m mod n = r,
4.3. OPERADORES Y EXPRESIONES ARITMETICAS 49
m n 9 4
r c mn 1 2 9 / 4
m mod n 9 % 4
Para asignar valores a variables se pueden utilizar los siguientes operadores infijos:
= : Asignacion. La parte de la izquierda que debe ser una variable. Sirve para almacenar
un dato en una variable. Asigna el valor de evaluar la parte de la derecha a la
variable de la parte de la izquierda. Por ejemplo, cuando se evalua la expresion
pi = 3.14159265, entonces se almacena el valor 3.14159265 en la variable pi.
+= : Asignacion con suma. La parte de la izquierda debe ser una variable. Suma la eva-
luacion de parte de la derecha con el valor almacenado en la variable definida en la
parte de la izquierda y guarda el resultado en la variable de parte de la izquierda.
Por ejemplo, la expresion x += 2, es equivalente a la expresion x = x + 2.
-= : Asignacion con resta. La parte de la izquierda debe ser una variable. Resta al valor
almacenado en la variable definida en la parte de la izquierda el resultado de la
evaluacion de parte de la derecha y guarda el resultado en la variable de parte de la
izquierda. Por ejemplo, la expresion x -= 2, es equivalente a la expresion x = x - 2.
*= : Asignacion con multiplicacion. La parte de la izquierda debe ser una variable. Mul-
tiplica el valor almacenado en la variable definida en la parte de la izquierda con la
evaluacion de parte de la derecha y guarda el producto en la variable de parte de la
izquierda. Por ejemplo, la expresion x *= 2, es equivalente a la expresion x = x * 2.
/= : Asignacion con division. La parte de la izquierda debe ser una variable. Divide el
valor almacenado en la variable definida en la parte de la izquierda entre el valor
de la evaluacion de la parte de la derecha y guarda el resultado en la variable de
parte de la izquierda. Por ejemplo, la expresion x /= 2, es equivalente a la expresion
x = x / 2. El valor de la evaluacion de la parte de la derecha debe ser distinto de
0.
%= : Asignacion con residuo. La parte de la izquierda debe ser una variable. Calcula el re-
siduo de dividir el valor almacenado en la variable definida en la parte de la izquierda
entre el valor de la evaluacion de la parte de la derecha y guarda el resultado en la
50 CAPITULO 4. INTRODUCCION A LOS LENGUAJES DE PROGRAMACION
Dos de los operadores mas utilizados para asignar valores a variables en programacion
son los operadores de incremento y decremento:
int x = 2;
int y = ++x;
se tiene que al final las variables almacenan los valores x = 3 y y = 3. El codigo anterior es
equivalente al siguiente codigo
int x = 2;
x = x + 1;
int y = x;
int x = 2;
int y = x++;
se tiene que al final las variables almacenan los valores x = 3 y y = 2. El codigo anterior es
equivalente al siguiente codigo
int x = 2;
int y = x;
x = x + 1;
4.3. OPERADORES Y EXPRESIONES ARITMETICAS 51
int x = 2;
int y = --x;
se tiene que al final las variables almacenan los valores x = 1 y y = 1. El codigo anterior es
equivalente al siguiente codigo
int x = 2;
x = x - 1;
int y = x;
int x = 2;
int y = x--;
se tiene que al final las variables almacenan los valores x = 1 y y = 2. El codigo anterior es
equivalente al siguiente codigo
int x = 2;
int y = x;
x = x - 1;
int x = 3;
int y = 2 * ++x;
52 CAPITULO 4. INTRODUCCION A LOS LENGUAJES DE PROGRAMACION
se tiene que al final las variables almacenan los valores x = 4 y y = 8. El codigo anterior es
equivalente al siguiente codigo
int x = 3;
x = x + 1;
int y = 2 * x;
int x = 3;
int y = 2 * x--;
se tiene que al final las variables almacenan los valores x = 2 y y = 6. El codigo anterior es
equivalente al siguiente codigo
int x = 3;
int y = 2 * x;
x = x - 1;
int x = 2;
int y = 4;
int z = ++x * y--;
se tiene que al final las variables almacenan los valores x = 3, y = 3 y z = 12. El codigo
anterior es equivalente al siguiente codigo
int x = 2;
int y = 4;
int aux = y;
x = x + 1;
int z = x * aux;
y = y - 1;
De entero a real: dado un dato o una variable de tipo entero, si se opera o se asigna
el dato o la variable con un dato o una variable de tipo real, entonces al realizar la
operacion o la asignacion, el dato entero se convierte (se promueve) a un dato de
tipo real de forma automatica, simplemente agregandole la parte decimal .0.
int n = 1;
double x = n;
double y = 0;
double z = -2;
n 1
x 1.0
y 0.0
z 2.0
Ejemplo. Las siguientes operaciones son equivalentes
De real a entero: dado un dato o una variable de tipo real, si se asigna el dato o la
variable a una variable de tipo entero, entonces el valor del dato o la variable se
convierte (se promueve) a un dato de tipo entero de forma automatica, simplemente
eliminando la parte decimal del real y dejando la parte entera.
double x = 1.0;
double y = -2.5;
int n = x;
int m = y;
int p = 3.14159265;
x 1.0
y 2.5
n 1
m 2
p 3
Si se desea convertir el valor de un dato o una variable de tipo real de forma directa,
sin necesidad de asignarlo a una variable, se pueden utilizar las instrucciones:
54 CAPITULO 4. INTRODUCCION A LOS LENGUAJES DE PROGRAMACION
(int)valor;
(int)variable;
2 * (int)2.5 2 * 2
(int)-3.14 * (int)5.5 -3 * 5
! : Operador de la negacion.
!
|| : Operador de la disyuncion.
||
== =
!=
> : Mayor que, devuelve V si el primer operador es estrictamente mayor que el segundo.
> >
4.3. OPERADORES Y EXPRESIONES ARITMETICAS 55
< : Menor que, devuelve V si el primer operador es estrictamente menor que el segundo.
< <
>= : Mayor o igual, devuelve V si el primer operador es mayor o igual que el segundo.
>=
<= : Menor igual, devuelve V si el primer operador es menor o igual que el segundo.
<=
0
5 4 3 2 1 0 1 2 3 4 5
1
!(a >= -2 && a < 3.5 && b > -1.25 && b <= 1.5) || (a * a + b * b <= 1)
42 / 6 + 7 * 3 - 39
i) (426) + 7 3 39 ( prioridad 4)
Operador(es) Prioridad
() 1
++(postincremento) --(postdecremento) 2
! -(signo menos) +(signo mas)
3
++(preincremento) --(predecremento)
* / % 4
+ - 5
< > <= >= 6
== != 7
&& 8
|| 9
= += -= *= /= %= 10
Tabla 4.1. Precedencia de los operadores en C++.
42 6 + 7 3 39 = 7 + 7 3 39
= 7 + 21 39
= 28 39
= 11
Observese la diferencia entre este ejemplo y siguiente ejemplo (de la vida real!), donde la
diferencia de los resultados esta dada por la prioridad con la cual se evaluan los operadores.
Ejemplo. Cual sera la forma correcta de escribir en C++ la operacion que aparece como
miembro izquierdo de la igualdad que se muestra en la siguiente imagen, de tal manera que
se obtenga como resultado de la evaluacion el numero que aparece como miembro derecho
de la igualdad
(((42 / 6) + 7) * 3) - 39
4.3. OPERADORES Y EXPRESIONES ARITMETICAS 57
12.0 * 3 - -4.0 + 8 / 2 % 3
(-2 + 5 % 3 * 4) / 4 + 2
i) ((2) + 5 % 3 4) 4 + 2 ( prioridad 3)
(2 + 5 % 3 4) 4 + 2 = ((2) + 5 % 3 4) 4 + 2
= ((2) + 2 4) 4 + 2
= ((2) + 8) 4 + 2
= (6) 4 + 2
=6 4+2
=1+2
=3
x = 3, y=4 y z = 2
x = y + z - 2;
t + 1. Con lo que los valores de las variables (memoria) en este nuevo instante de tiempo
seria:
x = 0, y=4 y z = 2
Ejemplo. Suponga que se desea realizar la asignacion
x = x + 3 - 2 * y
cuando x = 3 y y = 5.
Para entender como se realiza la asignacion es util subindizar las variables teniendo en
cuenta el instante de tiempo en el cual se esta leyendo o modificando la memoria. Con
base en lo anterior, la expresion se reescribe de la siguiente manera
xt + 1 = xt + 3 2 yt
x = x + 3 - 2 * y
cuando x = 3 y y = 5.
t x y
0 3 5
1 4 5
Ejemplo. Suponga que se desea ejecutar la siguiente secuencia de instrucciones
i = k + 1;
j = 2 * k;
i = i * k * j;
j = j * k - i;
60 CAPITULO 4. INTRODUCCION A LOS LENGUAJES DE PROGRAMACION
t k i j
0 1
1 1 2
2 1 2 2
3 1 4 2
4 1 4 2
4.5. EJERCICIOS 61
4.5. Ejercicios
1. Disenar un programa en C++ que permita evaluar la expresion
p || q && r
-b + b * b % 3 - 4 * a * c / 2 * a
(int)(b * c) % a * -b / c + d - a % d
int s = 0;
int i = 0;
s += i;
i++;
s += i;
i++;
s += i;
i++;
s += i;
i++;
s += i;
i++;
s += i;
i++;
s += i;
int p = 1;
int b = 2;
int t;
t = p;
p *= b;
t += p;
p *= b;
t += p;
p *= b;
t += p;
p *= b;
t += p;
p *= b;
t += p;
Si se repiten las dos ultimas instrucciones de forma repetida, cuales son las expre-
siones que se desean calcular con las variable p y t?.
Captulo 5
Relaciones y funciones
5.1. Relaciones
Una relacion R de A en B es un subconjunto del producto cartesiano A B, es decir,
R se dice relacion si R A B. Al conjunto A se le denomina conjunto de salida y al
conjunto B se le denomina conjunto de llegada.
DomR = a (a A) (b B) (a, b) R
Ejemplo. Sean A = {0, 1, 2} y B = {, , , }, dos conjuntos y sea R = (0, ), (0, ), (2, ), (2, ),
una relacion definida de A en B, el conjunto DomR = {0, 2} es el dominio de la relacion y
los elementos 0 y 2 son las preimagenes de la relacion R.
RanR = b (b B) (a A) (a, b) R
Ejemplo. Sean A = {0, 1, 2} y B = {, , , } dos conjuntos y sea R = (0, ), (0, ), (2, ), (2, )
una relacion definida de A en B, el conjunto RanR = {, , } es el rango de la relacion y
los elementos , y son las imagenes de la relacion R.
R
A B
0
1
2
Figura 5.1. Representacion de la relacion R = (0, ), (0, ), (2, ), (2, ) mediante diagramas
Sagitales.
Hay relaciones que se pueden establecer entre elementos del mismo conjunto, es decir,
una relacion que cumpla que R A A
R
A A
Figura 5.2. Representacion de la relacion R = (, ), (, ), (, ), (, ) mediante diagra-
mas Sagitales.
Una de las caractersticas mas importantes e interesantes que poseen las relaciones que
estan definidas sobre el mismo conjunto, son las propiedades que pueden cumplir; las cuales
permiten definir los conceptos de relaciones de orden y de equivalencia entre los elementos
de un conjunto. Dichas propiedades son las siguientes:
(a A)(a, a) R.
Ejemplo. Dada la relacion R = (0, 0), (0, 1), (1, 1), (1, 2), (2, 2) construida sobre el mis-
mo conjunto A = {0, 1, 2} se puede afirmar que
La relacion R es reflexiva pues estan todas las parejas de los elementos vinculados
consigo mismos (0, 0), (1, 1) y (2, 2).
Ejemplo. Dada la relacion R = (0, 0), (0, 1), (1, 1), (1, 2), (2, 2) construida sobre el mis-
mo conjunto A = {0, 1, 2} se puede afirmar que
La relacion R no es simetrica pues esta la pareja (0, 1) pero no esta la pareja (1, 0).
En este caso es suficiente con un caso que no se de para decir que una relacion no
cumple la propiedad.
Ejemplo. Dada la relacion R = (0, 0), (0, 1), (1, 1), (1, 2), (2, 2) construida sobre el mis-
mo conjunto A = {0, 1, 2} se puede afirmar que
La relacion R es antisimetrica pues cumple con la definicion, ya que las tres parejas
(0, 0), (1, 1) y (2, 2) son de la forma (a, a) que cumplen con la definicion, y para las
otras parejas (0, 1) y (1, 2) no estan presentes las parejas (1, 0) o (2, 1), por lo que
tambien se cumplen con la definicion de antisimetra.
Ejemplo. Dada la relacion R = (0, 0), (0, 1), (1, 1), (1, 2), (2, 2) construida sobre el mis-
mo conjunto A = {0, 1, 2} se puede afirmar que
La relacion R no es transitiva pues estan las parejas (0, 1) y (1, 2), pero no esta la
pareja (0, 2).
El hecho de que una relacion no sea simetrica no quiere decir que la relacion sea anti-
simetrica y viceversa.
Ejemplo. Si se tiene el conjunto A = {0, 1, 2}, y sobre este se define la relacion R =
(0, 0), (0, 1), (1, 0), (1, 2), (2, 2), se tiene que la relacion no es simetrica pues la pareja
(1, 2) esta, pero la pareja (2, 1) no esta, ni es antisimetrica pues las parejas (0, 1) y (1, 0)
estan, y es sabido que 1 0.
Ejemplo. Si se tiene el conjunto A = {0, 1, 2}, y sobre este se define la relacion R =
(0, 0), (1, 1), (2, 2), se tiene que la relacion es tanto simetrica como antisimetrica. Por
que?.
Una relacion R definida sobre el mismo conjunto, se dice que es una relacion de orden 1 ,
si y solo si, es reflexiva, antisimetrica y transitiva. Una relacion de orden se suele notar
con el smbolo A .
Ejemplo. Si se tiene el conjunto A = {0, 1, 2}, y la relacion R = (0, 1), (0, 2), (0, 0), (1, 1), (1, 2), (2, 2)
esta es una relacion de orden, pues es reflexiva, antisimetrica y transitiva.
1
Tambien se suele denominar relacion de orden parcial.
5.1. RELACIONES 67
0 1 2
Una relacion de orden total, es una relacion de orden donde para todo a, b A se cumple
al menos una de las desigualdades a A b o b A a.
Una relacion R se dice que es una relacion de equivalencia, si y solo si, es reflexiva,
simetrica y transitiva. El smbolo utilizado para decir que una relacion es equivalente es
A .
Dado el conjunto A = {0, 1, 2} y una relacion R definida sobre A de la siguiente ma-
nera R = (0, 0), (0, 1), (1, 0), (1, 1), (2, 2), se puede observar que R es una relacion de
equivalencia, pues:
Las relaciones de equivalencia tienen una particular caracterstica, es que los elementos
que estan relacionados se pueden interpretar como que representan el mismo objeto. As,
una relacion de equivalencia define una particion del conjunto en grupos de conjuntos con
propiedades similares; tales como que no son vacos, que no tienen elementos en comun, y
que la union de todos los grupos es el conjunto inicial. A estos grupos se les conoce como
clases de equivalencia.
Ejemplo. Para el conjunto A = {0, 1, 2} y la relacion de equivalencia definida sobre el
mismo conjunto R = (0, 0), (0, 1), (1, 0), (1, 1), (2, 2), aqu se observa que se pueden for-
mar los grupos {0, 1} y {2}, los cuales son una particion del conjunto A y que definen dos
68 CAPITULO 5. RELACIONES Y FUNCIONES
clases de equivalencia. Observese que los valores 0 y 1, resultan ser equivalentes, es decir,
que representan el mismo objeto.
0 1 2
f (x) = y
para expresar que (x, y) f . Cuando se desea especificar tanto el conjunto de salida como
el conjunto de llegada se usa la notacion dominiorango
f AB
x f (x)
Las funciones tambien poseen propiedades muy interesantes, as como las de las rela-
ciones de un conjunto en si mismo, las mas importantes de estas son:
5.2. FUNCION PARCIAL 69
f
A B
0
1
2
3
4
Figura 5.3. Representacion de la funcion f = (0, ), (1, ), (4, ) mediante diagramas Sagi-
tales.
f
A B
0
1
2
Figura 5.4. Representacion de la relacion f = (0, ), (1, ), (2, ), (1, ) mediante diagra-
mas Sagitales.
f
A B
0
1
2
Figura 5.5. Representacion de la funcion inyectiva f = (0, ), (2, ) mediante diagramas
Sagitales.
f
A B
0
1
2
3
4
Figura 5.6. Representacion de la funcion sobreyectiva f = (0, ), (1, ), (2, ), (4, ) me-
diante diagramas Sagitales.
f
A B
0
1
2
3
4
Figura 5.7. Representacion de la funcion total f = (0, ), (1, ), (2, ), (3, ), (4, ) median-
te diagramas Sagitales.
f
A B
0
1
2
3
Figura 5.8. Representacion de la funcion biyectiva f = (0, ), (1, ), (2, ), (3, ) mediante
diagramas Sagitales.
f
A B
0
1
2
3
4
72 CAPITULO 5. RELACIONES Y FUNCIONES
Una alternativa para obtener una funcion total a partir de una funcion parcial es la de
asignar los valores del conjunto de salida que no pertenecen al dominio a algun valor del
conjunto de llegada, como se muestra a continuacion
f
A B
0
1
2
3
4
f
A B
0
1
2
3
4
div R R R
(x, y) ,
x
y
se tiene que si la segunda proyeccion de la pareja del dominio (x, y) es igual a 0, entonces
la funcion se encuentra indefinida, por lo tanto la funcion no es total.
Para hallar una funcion que contenga la anterior y que sea total, se adicional el smbolo
al conjunto de llegada y se extiende la funcion de la siguiente manera
div R R R {}
, si y = 0;
(x, y) x
y , en otro caso.
5.4. FUNCIONES IMPORTANTES EN COMPUTACION 73
idA A A
x idA (x) = x
idA
A A
Figura 5.9. Representacion de la funcion identidad idA = (, ), (, ), (, ), (, ) me-
diante diagramas Sagitales.
x R R0,+
x, si x 0;
x
x, en otro caso.
Definicion. Potencia
La funcion potencia de b elevado al exponente n se denota como bn y se define como:
bn R Z R {}
si (b 0) (n = 0);
1,
b b b, si (b 0) (n Z+ );
1 nveces
(b, n)
si (b 0) (n Z );
,
bn
si (b = 0) (n > 0);
0,
, si (b = 0) (n 0).
74 CAPITULO 5. RELACIONES Y FUNCIONES
En programacion se define que x12 = x y se puede demostrar que x2 = x.
Definicion. Logaritmo
La funcion logaritmo en base b de x se denota como logb x y se define como:
logb x R+ R+ R
(b, x) y, donde by = x.
Ejemplos. log2 4 = 2, log2 8 = 3, log2 1 = 0 (en general logb 1 = 0), loge e = 1 (en general
logb b = 1), log3 19 = 2, log0.5 0.125 = 3, log0.25 2 = 12 .
Definicion. Piso
La funcion piso de x se denota como x y se define como:
x R Z
x n, donde (n Z) (n x < n + 1).
f (x) = x 2
4 3 2 1 1 2 3 4
Definicion. Techo
La funcion techo de x se denota como x y se define como:
x R Z
x n, donde (n Z) (n 1 < x n).
f (x) = x 2
4 3 2 1 1 2 3 4
Definicion. Truncamiento
La funcion truncamiento de x se denota como trunc(x) y se define como:
trunc(x) R Z
x, si x 0;
x
x,
si x < 0.
a partir de la definicion anterior se tiene que en C++ se cumple que (int)x = trunc(x).
76 CAPITULO 5. RELACIONES Y FUNCIONES
f (x) = trunc(x) 2
4 3 2 1 1 2 3 4
frac(x) R [0, 1)
x x x.
4 3 2 1 1 2 3 4
f (x) = frac(x) 1
Definicion. Redondeo
La funcion redondeo de x se denota como round(x), retorna el entero mas proximo al
numero x. Para los reales no negativos retorna el techo si la parte fraccionaria es mayor o
igual a 0.5, retorna el piso si la parte fraccionaria es menor a 0.5. Para los reales negativos
retorna el piso si la parte fraccionaria es mayor o igual a 0.5, retorna el techo si la parte
fraccionaria es menor a 0.5. Formalmente esto se define como:
5.5. COMPOSICION DE FUNCIONES 77
round(x) R Z
x, si (x 0) frac(x) 0.5;
x x, si (x 0) frac(x) < 0.5;
round(x), si x < 0.
f (x) = round(x) 2
Contexto en matematicas:
[x] = x
Contexto en computacion:
f g AC
a f (g(a))
78 CAPITULO 5. RELACIONES Y FUNCIONES
Una representacion que permite entender mejor como opera esta nueva funcion, es
utilizando un diagrama conmutativo, como se muestra a continuacion:
g
A B
f g
f
g f
A B C
1 a
2
3 b
4
c
5
6 _ d
f g
f g
A C
1 a
2
3 b
4 c
5
6 d
Figura 5.11. Representacion mediante diagramas de la funcion f g =
(1, a), (2, d), (3, c), (4, c), (6, c).
5.5. COMPOSICION DE FUNCIONES 79
gRZ f ZZ
x x nnn
f g RZ
x f g(x) = f x = x x
i = k + 1;
j = 2 * k;
i = i * k * j;
j = j * k - i;
i = +(k, 1)
j = (2, k)
i = (i, k), j = + (k, 1), k, (2, k)
j = (j, k), i = (2, k), k, + (k, 1), k, (2, k)
5.6. Ejercicios
i. R1 = (l, l), (l, n), (n, l), (n, n), (s, u), (u, l), (u, u)
ii. R2 = (l, l), (l, n), (n, l)
iii. R3 = (l, l), (l, n), (l, u), (n, l),
(n, n), (s, s), (u, l), (u, u)
iv. R4 = (n, l), (s, l), (s, n), (u, l), (u, n), (u, s)
v. R5 = (l, l), (l, n), (l, s), (l, u), (n, n), (n, s),
(n, u), (s, s), (s, u), (u, u)
vi. R6 = {(s, u)
6. De las relaciones del numeral 4. Cuales son reflexivas?, Cuales son simetricas?,
Cuales son antisimetricas?, Cuales son transitivas?.
7. De las relaciones del numeral 4. Cuales son una relacion de orden?, Cuales son una
relacion de equivalencia?.
11. De las relaciones definidas en el numeral 10. Cual es el dominio?, Cual es el rango?.
12. De las relaciones definidas en el numeral 10 que son funciones. Cuales son inyecti-
vas?, cuales son sobreyectivas?, cuales son totales?, cuales son biyecciones?.
Captulo 6
Funciones en programacion y la estructura
condicional
f RR
(x) x2
f = (x, x2 ) (x R).
Primero se escribe el tipo de retorno (rango). Como es real, el tipo de dato es double.
double
double f
Entre parentesis se coloca el tipo y la variable de las variables del dominio. En este
caso solamente se tiene la variable x quedando double x y se coloca una llave abierta
{.
En las siguientes lneas se escribe la definicion de la funcion entre las llaves termi-
nando con punto y coma ; cada linea de la funcion. Dicha definicion de funcion
corresponde al algoritmo o computo, para generar la imagen calculada de la funcion
se utiliza la palabra clave return, de la siguiente manera
Otra posible definicion de la funcion podra escribirse almacenando el valor del producto
x * x en una variable de tipo double y retornandolo as:
f (x) = y
area circulo R R
(r) 3.14159265 r r
Notese que para definir el valor se tomo como aproximacion el valor 3.14159265.
En vez de elevar el valor del radio al cuadrado se tomo la multiplicacion de r r ya
que la potencia no es una operacion matematica basica. En la seccion de recursividad se
definira potencia como una funcion.
Esta funcion se traduce al lenguaje C++ paso a paso de la siguiente forma:
Primero se escribe el tipo de retorno en este caso el conjunto que corresponde al tipo
de dato del area del crculo, como es real el tipo de dato es double.
double
double area_circulo
Entre parentesis se coloca el tipo y la variable de las variables del dominio. En este
caso solamente se tiene la variable r de tipo double r y se coloca una llave abierta
{.
En las siguientes lneas se escribe el calculo del area del crculo y se retorna el valor
calculado.
Otra posible definicion de la funcion podra escribirse almacenando el valor del area del
crculo en una variable de tipo double y retornandolo as:
#include<iostream>
#include<cstdlib>
/*
En esta parte se definen las funciones
*/
int main(){
/*
En esta parte se realiza la lectura de datos,
y los llamados a las funciones
*/
cout << endl;
system("pause"); //windows
return EXIT_SUCCESS;
};
Para el caso del area del crculo, el archivo fuente en C++ sera el siguiente, en el cual
se han separado el encabezado del archivo, la funcion del calculo del area y la funcion
principal
#include<iostream>
#include<cstdlib>
int main(){
double radio;
cout << "radio del circulo? = ";
cin >> radio;
cout << "El area del circulo es: ";
cout << area_circulo(radio);
cout << endl;
system("pause"); //windows
return EXIT_SUCCESS;
};
88 CAPITULO 6. FUNCIONES EN PROGRAMACION Y LA ESTRUCTURA CONDICIONAL
Como se aprecia en el programa anterior, se utilizan las funciones cin y cout que perte-
necen a la librera de entrada y salida de flujos de datos iostream. Las dos primeras lneas
de codigo permiten al compilador incluir las definiciones de estas funciones en el programa
principal. La funcion cout lo que hace es mostrar una cadena de caracteres (texto) en la
consola. La instruccion cout << endl, hace que se oblige a generar una nueva lnea en la
consola. La funcion cin lo que hace es asignar el valor que sea digitado en la consola a la
variable de la parte de la izquierda del operador <<. En la instruccion cin >> radio; se
asigna a la variable radio el valor digitado por el usuario. system("pause") lo que hace
es ejecutar el comando pause de Windows que permite pedirle al usuario que presione una
tecla para continuar la ejecucion del programa o en este caso por estar antes del retorno
o fin de la funcion principal para salir de el devolviendo al sistema operativo un valor de
EXIT_SUCCESS para indicar que ejecucion del programa fue satisfactoria, es decir, que en
este caso el programa se ejecuto correctamente.
El programa anterior pide al usuario digitar el radio del crculo y almacena el valor de
la lectura en la variable radio. Posteriormente despliega un mensaje y se realiza el llamado
a la funcion area_circulo. Notese que los nombres de variables (en este caso radio) en
el programa principal no necesariamente deben coincidir con los de la declaracion de la
funcion (en este caso la funcion recibe un valor de tipo double llamado r), sin embargo
se debe notar que su tipo de dato s debe ser el mismo.
area rectangulo R R R.
Para el calculo del area de un rectangulo es necesario conocer el largo y el ancho del
rectangulo, a partir de los cuales el area del rectangulo esta dada por la expresion Ar = la,
donde las variables estan definidas as:
area rectangulo R R R
(l, a) l a
Primero se escribe el tipo de retorno en este caso el conjunto que corresponde al tipo
de dato del area del rectangulo, como es real el tipo de dato es double.
double
double area_rectangulo
En las siguientes lneas se escribe el calculo del area del rectangulo, se retorna el
valor calculado y se cierra la definicion de la funcion.
#include<iostream>
#include<cstdlib>
int main(){
double largo;
double ancho;
cout << "largo? = ";
cin >> largo;
cout << "ancho? = ";
cin >> ancho;
cout << "El area del rectangulo es: ";
cout << area_rectangulo(largo, ancho);
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
6.3.1. El condicional if
Es posible tener programas en los que se deban cubrir diferentes casos, para los cuales
se deberan retornar diferentes valores dadas unas condiciones.
La estructura de control condicional o de seleccion permite ejecutar, o un grupo de
instrucciones u otro grupo si una condicion se cumple o no, un condicional en C++ se
especifica mediante el siguiente fragmento de codigo
if(<cond>){
<body_1>
}else{
<body_2>
};
valor absoluto R R
x, si x 0;
(x)
x, en otro caso.
#include<iostream>
#include<cstdlib>
int main(){
double x;
cout << "x? = ";
cin >> x;
cout << "El valor absoluto es: ";
cout << valor_absoluto(x);
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
aqu se tienen dos casos, si el numero a es mayor que b el valor maximo es a; en otro caso
se debe retornar b. En notacion matematica esto puede ser escrito de la siguiente forma
La regla de traduccion a funcion es similar a la anterior, solo hay que tener en cuenta
la instruccion condicional, y que si no se cumple la condicion especificada en el if, se
ejecutara el flujo de instrucciones especificado bajo el alcance del else
if(<cond>){
<body_1>
}else{
<body_2>
};
Ejemplo. La siguiente funcion permite calcular el valor absoluto de un numero real, pero
utilizando el operador condicional ?: en vez del condicional if presentado en un ejemplo
previo
Ejemplo. Una funcion equivalente a la anterior, que es mas compacta y que tambien
permite calcular el valor absoluto, es la siguiente
if(<cond>){
<body>
};
observese como la ejecucion del cuerpo del condicional no afecta las instrucciones que
siguen despues del condicional.
(p) (q) (p q)
V V V
V F F
F V V
F F V
se puede definir una funcion que permite calcular la operacion condicional de un par de va-
riables booleanas y que retorna el resultado de operar los valores mediante un condicional,
de la siguiente manera
condicional B B B
aqu se tienen dos casos, primero, si el antecedente es verdadero y el consecuente es fal-
so, entonces el resultado de aplicar el condicional el falso, para cualquier otro caso el
condicional es verdadero. En notacion matematica esto puede ser escrito de la siguiente
manera
condicional B B B
F, si (p) = V (q) = F ;
(p, q)
V, en cualquier otro caso.
observese que es posible construir una funcion que utilice solo una estructura if sin la
sentencia else que es mucho mas sencilla que la funcion presentada anteriormente,
en esta funcion se tiene en cuenta que si la premisa p tiene valor true, entonces el resultado
esta dado por el valor de la conclusion q, y si el valor de p es false, entonces el condicional
tendra como valor true.
Otra de las opciones para utilizar una estructura if es la de enlazar varias estructuras
if, de tal manera que solamente se pueda ejecutar un grupo de instrucciones dependiendo
de cual de las opciones se evalua verdadero. De la misma manera que en el caso anterior
la parte else final es opcional. La codificacion en C++ de las estructuras if enlazadas es
la siguiente
if(<cond_1>){
<body_1>
}else if(<cond_2>){
<body_2>
}
...
}else if(<cond_i>){
<body_i>
}
...
}else if(<cond_n-1>){
<body_n-1>
}else{
<body_n>
};
96 CAPITULO 6. FUNCIONES EN PROGRAMACION Y LA ESTRUCTURA CONDICIONAL
entonces
pago f inal Z R R
n precio, n 5;
n precio 0.95, 5 < n 10;
(n, precio)
n precio 0.90, 10 < n 20;
n precio 0.80, en otro caso.
Cuando se tiene una instruccion if enlazada en la cual las condiciones consisten en com-
parar una misma variable con un grupos de valores enteros constantes de forma repetida,
como la que se presenta a continuacion
98 CAPITULO 6. FUNCIONES EN PROGRAMACION Y LA ESTRUCTURA CONDICIONAL
if(<var_entera> == <num_1>){
<body_1>
}else if(<var_entera> == <num_2>){
<body_2>
}
...
}else if(<var_entera> == <num_i>){
<body_i>
}
...
}else if(<var_entera> == <num_n-1>){
<body_n-1>
}else{
<body_n>
};
en este caso se utiliza una instruccion switch, la cual sirve para abreviar una instruccion
if enlazada como la anterior. El aspecto general de una instruccion switch es la siguiente:
Cada uno de los valores enteros constantes se trata como un caso, especificando la
palabra case seguido de la constante y terminando con : (dos puntos).
Se termina con una instruccion break que obliga a que se deje de ejecutar la ins-
truccion switch.
switch(<var_entera>){
case <num_1>:
<body_1>
break;
case <num_2>:
<body_2>
break;
...
case <num_i>:
<body_i>
break;
...
case <num_n-1>:
<body_n-1>
break;
default:
<body_n>
break;
};
Cuando en una instruccion switch varios casos se tratan de la misma forma, entonces
estos se pueden agrupar en uno o varios casos, como se muestra en el siguiente ejemplo.
Es usual que las instructiones que se ejecutan dentro de los casos de una instruccion
switch se retornen directamente cuando se calculen dentro de una funcion, para estos
casos, en vez de dejar de ejecutar el switch con un break, se puede retornar el valor
directamente mediante el uso de la instruccion return. Si se elije esta opcion no se debe
utilizar la instruccion break. A continuacion se muestra esta variacion de la instruccion
switch.
Ejemplo. Deteccion de vocales minusculas III
En este ejemplo se agruparon todos lo casos de las vocales en uno solo y se retorno di-
rectamente el resultado de la evaluacion de cada caso.
#include<iostream>
#include<cstdlib>
int main(){
double largo;
double ancho;
cout << "largo? = ";
cin >> largo;
if(largo < 0){
cout << "El largo no es valido";
cout << endl;
system("pause");
return EXIT_FAILURE;
};
cout << "ancho? = ";
cin >> ancho;
if(ancho < 0){
cout << "El ancho no es valido";
cout << endl;
system("pause");
return EXIT_FAILURE;
};
cout << "El area del rectangulo es: ";
cout << area_rectangulo(largo, ancho);
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
104 CAPITULO 6. FUNCIONES EN PROGRAMACION Y LA ESTRUCTURA CONDICIONAL
6.5. Ejercicios
1. Hacer un programa que dado el area del corral de unas gallinas y el numero de
gallinas en el corral determine el area que le corresponde a cada gallina.
2. Construir una funcion que dados tres numeros reales calcule el maximo de los tres.
3. Dadas las longitudes de los dos brazos de una palanca y el peso puesto en el brazo
mas largo de la palanca, calcular el peso que se puede poner en el brazo mas corto
para que la palanca quede en equilibrio.
4. Dadas las longitudes de los dos brazos de una palanca y el peso puesto en el brazo
mas corto de la palanca, calcular el peso que se puede poner en el brazo mas largo
para que la palanca quede en equilibrio.
5. Dados los pesos que se pueden poner en cada uno de los lados de la palanca y la
longitud total de la palanca determinar la longitud del brazo mas largo para que la
palanca quede en equilibrio.
6. Dados los pesos que se pueden poner en cada uno de los lados de la palanca y la
longitud total de la palanca determinar la longitud del brazo mas corto para que la
palanca quede en equilibrio.
7. Para crear un litro del compuesto D, se requiere que su composicion por partes
este conformada de la siguiente manera, 5 partes deben ser del producto A, 8 partes
deben ser del producto B y 7 partes deben ser del producto C. Si se requiere crear
10 litros del compuesto D. Cuantos litros del producto A se requieren?, Cuantos
litros del producto B se requieren?, Cuantos litros del producto C se requieren?.
11. Dadas tres longitudes positivas, determinar si con esas longitudes se puede construir
un triangulo.
Captulo 7
Flujos de entrada y salida
7.1. Definicion
Un flujo es un objeto desde el cual se puede enviar o recibir informacion.
Para el caso de una fuente de entrada de informacion, esta puede ser enviada desde
el teclado o desde un archivo o desde una red local de comunicaciones o desde un
nodo de internet, entre otros.
Para el caso de una fuente de salida de informacion, esta tpicamente es enviada a
la consola (pantalla) o a un archivo o una impresora u otro nodo de internet.
Los archivos son ejemplos de flujos de doble direccion, se puede recibir y se puede
enviar informacion desde y hacia ellos.
En captulos anteriores ya se haba hecho uso de los flujos; con el objeto cin se reciba
informacion desde el teclado y con el objeto cout se enviaba informacion a la consola de
salida en la pantalla. En este capitulo, ademas de estudiar los flujos cin y cout, se tratara el
tema de usar archivos como ejemplos de flujos de entrada y salida de informacion distintos
al teclado y la consola.
IOS S
S
IOS
IS OS
IFS cin OFS cout
#include<iostream>
#include<cstdlib>
leer T IS T
(is) a, donde a = leer(is)
T leer_T(istream& is){
T a;
is >> a;
return a;
};
La funcion leer(is) que en C++ se escribe como >>, esta retorna el dato siguiente que
se encuentre almacenado en el flujo is.
Cuando un flujo se utiliza como parametro, este se pasa por referencia, es decir, que
fsicamente no se pasa un valor como parametro, como en el caso de los tipos primitivos,
sino que se pasa su direccion de memoria. Para pasar la direccion de memoria de un flujo
se coloca el smbolo & inmediatamente despues del tipo de flujo; como en el caso anterior
que se escribio istream&.
Ejemplo. En C++ para leer un dato de tipo entero desde un flujo se utiliza la siguiente
funcion
1 2
-5 -5
5
a a
108 CAPITULO 7. FLUJOS DE ENTRADA Y SALIDA
5
a
escribir T T OS OS
(a, os) os, donde escribir(a, os)
La funcion escribir(a, os) que en C++ se escribe como <<, esta escribe el dato a en el
flujo os. En la funcion escribir_T se enva adicionalmente el smbolo \t para separar
el smbolo a del siguiente dato que sea almacenado en el flujo os.
Ejemplo. En C++ para escribir un dato de tipo entero en un flujo se utiliza la siguiente
funcion
1 2
a a
5 5
5
7.4. FLUJOS DE ENTRADA Y SALIDA DESDE Y HACIA ARCHIVOS 109
4
3
a
-5
5
5 -5
Ejemplo. Para utilizar las funciones anteriores, que leen desde el teclado y escriben en la
consola se pueden llamar de la siguiente forma
int main(){
cout << "Digite un entero: ";
int a = leer_int(cin);
cout << "El entero leido es: ";
escribir_int(a, cout);
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
Digite un entero: -5
El entero leido es: -5
Presione una tecla para continuar . . .
#include<fstream>
con lo cual el encabezado de un archivo fuente de un programa en C++ que haga uso de
archivos como flujos tendra el siguiente aspecto
#include<iostream>
#include<cstdlib>
#include<fstream>
Para declarar que un archivo f pertenece al flujo fuente de entrada IFS (f IFS),
en C++ se especifica que f pertenece al conjunto ifstream y se debe proporcionar la
ubicacion del archivo en el computador donde se ejecute el programa, es necesario que el
archivo exista previamente.
Para crear un flujo de entrada en C++ y especificar la ruta de localizacion del archivo
que sirve de flujo de entrada se utiliza la siguiente sintaxis
ifstream f("<path>");
C:\\mis documentos\\archivo.txt
/home/user/archivo.txt
Para declarar que un archivo f pertenece al flujo de salida OFS (f OFS), en C++
se especifica que f pertenece al conjunto ofstream y se debe proporcionar la ubicacion
del archivo en el computador donde se ejecute el programa, en este caso no es necesario
que el archivo exista previamente.
Para crear un flujo de salida en C++ y especificar la ruta de localizacion del archivo
que sirve de flujo de salida se utiliza la siguiente sintaxis
ofstream f("<path>");
Las reglas para la especificacion de la ruta de localizacion son las mismas que se des-
cribieron para los archivos como flujos de entrada.
7.4. FLUJOS DE ENTRADA Y SALIDA DESDE Y HACIA ARCHIVOS 111
Una paso necesario cuando se utilizan archivos como flujos de entrada o salida es que es
necesario cerrar los archivos despues de utilizarlos para evitar que al ser abiertos queden
bloqueados para ser usados por otras aplicaciones o que al escribir la informacion no se
escriba completamente en el archivo. Para hacer esto se llama la funcion close() con la
sintaxis
f.close();
Ejemplo. Suponga que se dispone del archivo de texto plano entrada.txt con las si-
guiente informacion
0
1
2
3
4
5
y se quiere leer de este archivo para copiar los primeros 4 enteros del archivo al archivo
salida.txt, esto se podra hacer utilizando el siguiente programa
#include<iostream>
#include<cstdlib>
#include<fstream>
int main(){
ifstream ifs("entrada.txt");
ofstream ofs("salida.txt");
escribir_int(leer_int(ifs), ofs);
escribir_int(leer_int(ifs), ofs);
escribir_int(leer_int(ifs), ofs);
escribir_int(leer_int(ifs), ofs);
ofs.close();
ifs.close();
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
0 1 2 3
Esta declaracion de flujo sobreescribe el archivo cada vez que se ejecuta el programa.
Notese que cada dato con esta sintaxis se lee hasta encontrar uno de los siguientes ca-
racteres especiales: \t, \n, . La primera vez que se entra en el ciclo for se lee el
entero 0, luego se realiza la lectura del 1, luego se realiza la lectura del 2 y finalmente se
lee el entero 3, cada uno de esos numeros se escriben en el archivo de salida junto con un
smbolo \t y a continuacion se procede a cerrar los flujos.
7.4. FLUJOS DE ENTRADA Y SALIDA DESDE Y HACIA ARCHIVOS 113
Ejercicios
1. Modele mediante una funcion matematica y disene una funcion en C++ que permita
leer un dato de tipo real desde un flujo generico.
2. Modele mediante una funcion matematica y disene una funcion en C++ que permita
escribir un dato de tipo real en un flujo generico.
3. Escriba un programa en C++ que lea un dato de tipo real (p. ej. 3.14159265) desde
el flujo de datos suministrado por el teclado usando la funcion disenada anteriormente
en el numeral 1 y que escriba el opuesto aditivo del numero en la consola usando la
funcion disenada anteriormente en el numeral 2 (p. ej. -3.14159265).
4. Escriba un programa en C++ que lea un dato de tipo real (p. ej. -3.14159265)
desde el flujo de datos suministrado por un archivo de entrada llamado "input.txt"
usando la funcion disenada anteriormente en el numeral 1 y que escriba el opuesto
aditivo del numero en un archivo de salida llamado "output.txt" usando la funcion
disenada anteriormente en el numeral 2 (p. ej. 3.14159265).
5. Modele mediante una funcion matematica y disene una funcion en C++ que permita
leer un dato de tipo booleano desde un flujo generico.
6. Modele mediante una funcion matematica y disene una funcion en C++ que permita
escribir un dato de tipo booleano en un flujo generico.
7. Escriba un programa en C++ que lea un dato de tipo booleano (p. ej. 0) desde el
flujo de datos suministrado por el teclado usando la funcion disenada anteriormente
en el numeral 5 y que escriba la negacion del dato ledo previamente en la consola
usando la funcion disenada anteriormente en el numeral 6 (p. ej. 1).
8. Escriba un programa en C++ que lea un dato de tipo booleano (p. ej. 1) desde el
flujo de datos suministrado por un archivo de entrada llamado "input.txt" usando
la funcion disenada anteriormente en el numeral 5 y que escriba la negacion del dato
ledo previamente en un archivo de salida llamado "output.txt" usando la funcion
disenada anteriormente en el numeral 6 (p. ej. 0).
9. Disenar y escribir un programa que lea los mismos numeros enteros del archivo del
ejemplo de la seccion 7.4.4, que imprima el primer numero en la consola, el segundo
en el archivo de salida, el tercero en la consola y el cuarto en el archivo de salida.
10. Disenar y escribir un programa que lea los mismos numeros enteros del archivo del
ejemplo de la seccion 7.4.4, que imprima el segundo y el tercero en el archivo de
salida.
11. Disenar y escribir un programa que lea los mismos numeros enteros del archivo del
ejemplo de la seccion 7.4.4, que imprima los primeros cuatro numeros tanto en un
archivo de salida como en la consola.
114 CAPITULO 7. FLUJOS DE ENTRADA Y SALIDA
12. Modele mediante una funcion matematica y disene una funcion en C++ que permita
leer un dato de tipo caracter desde un flujo generico.
13. Modele mediante una funcion matematica y disene una funcion en C++ que permita
escribir un dato de tipo caracter en un flujo generico.
14. Supongase que se dispone de un archivo que contiene los siguientes caracteres sepa-
rados por el smbolo \t
a e i o u a e i o u
Disenar un programa en C++ que lea caracter por caracter desde el flujo de datos
suministrado por el archivo usando la funcion disenada anteriormente en el nume-
ral 12, que almacene los caracteres en variables y que luego escriba los caracteres en
orden inverso en un archivo de salida usando la funcion disenada anteriormente en
el numeral 13, es decir, el archivo de salida tendra el siguiente aspecto
u o i e a u o i e a
Captulo 8
Funciones recursivas
8.1. Definicion
Definicion. En 1952 Stephen Kleene definio formalmente en [Kleene 1952] que una fun-
cion parcial recursiva de enteros no negativos es cualquier funcion f definida por un
sistema no contradictorio de ecuaciones de las cuales las partes derechas e izquierdas estan
compuestas a partir de:
iii. La constante 0, y
Ejemplo. El siguiente es un sistema que define la funcion parcial recursiva f (x, y) que
permite computar el producto de x con y.
f (x, 0) = 0
f x, s(y) = gf (x, y), x
g(x, 0) = x
gx, s(y) = sg(x, y)
Notese que las ecuaciones podran no determinar el valor de f para cada posible entrada,
y que en ese sentido la definicion es lo que se definio como funcion parcial. Si el sistema
de ecuaciones determina el valor de f para cada entrada, entonces la definicion es lo que
se definio como funcion total. Cuando se usa el termino funcion recursiva, en este caso se
esta hablando de forma implcita de que la funcion recursiva es total.
115
116 CAPITULO 8. FUNCIONES RECURSIVAS
El conjunto de funciones que pueden ser definidas recursivamente en esta forma se sabe
que son equivalente a el conjunto de funciones computables por una maquina de Turing o
por medio del lambda calculo.
Ya que este libro es un texto introductorio a la programacion, no se trataran las funcio-
nes recursivas con todo su detalle formal ya que esto esta mucho mas alla del alcance de
este libro; en cambio se intentara caracterizar mas concretamente las funciones recursivas
que usualmente son utilizadas a un nivel introductorio de la programacion, mediante la
siguiente definicion debilitada de funcion recursiva. Hay que tener en mente que no se
pretende que esta caracterizacion sea exhaustiva con respecto al conjunto de todas las
funciones recursivas.
bn = b b b b b
nveces
si se usa la propiedad asociativa del producto de numeros reales, se tiene que
8.2. EJEMPLOS DE PROBLEMAS QUE PUEDEN RESOLVERSE RECURSIVAMENTE 117
bn = b b b b b = (b b b b) b
nveces n1veces
lo que es equivalente a
bn = b b b b b = (b b b b) b = bn1 b
nveces n1veces
A partir de esta observacion se puede dar una definicion recursiva usando funciones.
La declaracion de esta funcion junto con su cuerpo se hara de la siguiente manera
potencia(b, n) = p
b = Base
n = Exponente
p = Potencia bn
entonces
potencia R N R
1, si n = 0;
(b, n)
potencia(b, n 1) b, en otro caso.
#include<iostream>
#include<cstdlib>
int main(){
double b;
int n;
cout << "b? = ";
cin >> b;
cout << "n? = ";
cin >> n;
cout << "potencia(b,n) = ";
cout << potencia(b,n);
cout << "\n";
system("pause");
return EXIT_SUCCESS;
};
$1 000.000
lo que se deba pagar en el mes anterior mas los intereses de esa cantidad.
As, si m = 1000000, i = 0.05 y n = 12, se tiene que pago(1000000, 0.05, 12) =
1795856.326.
A partir de las observaciones anteriores, ya se detecta la regla recursiva con la que se
puede calcular el interes compuesto mes vencido en general, con lo cual se puede disenar
una funcion recursiva que permita calcular el valor total a pagar para cualquier monto,
cualquier interes y cualquier intervalo de tiempo.
8.2. EJEMPLOS DE PROBLEMAS QUE PUEDEN RESOLVERSE RECURSIVAMENTE 119
pago(m, i, n) = valor
entonces
cout.precision(10);
#include<iostream>
#include<cstdlib>
int main(){
cout.precision(10);
double m;
double i;
int n;
cout << "m? = ";
cin >> m;
cout << "i? = ";
cin >> i;
cout << "n? = ";
cin >> n;
cout << "pago(m,i,n) = ";
cout << pago(m,i,n);
cout << "\n";
system("pause");
return EXIT_SUCCESS;
};
Suponga que selecciona cuatro cartas distintas de una baraja de poker, que se van a
representar por los smbolos
1. Se selecciona una carta del conjunto cartas de forma arbitraria pero fija, por ejemplo
la carta .
2. Ya fijada la carta , el resto del trabajo consiste en hallar el numero de formas dis-
tintas de organizar las cartas restantes, es decir, el conjunto cartas{} = , , .
Como la seleccion de las cartas se hizo de forma arbitraria, entonces, para poder listar
todos los posibles ordenamientos, se tiene que el paso del numeral 1 se puede realizar
de cuatro formas. Por cada una de estas escogencias se hace la seleccion de una carta
de un conjunto con un elemento menos, como ocurre en el paso del numeral 3; esto se
puede realizar de tres formas posibles. Por cada par de escogencias se hace la seleccion de
una carta de un conjunto con dos elementos menos, como ocurre en el paso del numeral
5; esto se puede realizar de dos formas posibles. Por cada tro de escogencias se hace la
seleccion de una carta de un conjunto con tres elementos menos. Para este caso el conjunto
restante tiene un solo elemento y por lo tanto solo hay una posible seleccion. De lo anterior
se concluye que el numero de formas de listar los elementos de un conjunto con cuatro
elementos es
4 3 2 1 = 24
122 CAPITULO 8. FUNCIONES RECURSIVAS
El listado de las 24 posibles formas en que se pueden organizar las cuatro cartas es el
siguiente
En general, para un conjunto A con cardinal A = n, se tiene que el numero de formas
de listar todas lo formas en que se pueden organizar los elementos de A es
n (n 1) (n 2) 3 2 1
este valor depende solamente de n, es una funcion, se denota por el smbolo n! y se llama
es factorial del numero n. Para el caso del conjunto , se puede demostrar que 0! = 1.
n! = n (n 1) (n 2) 3 2 1
A partir de las observaciones anteriores se puede obtener la funcion recursiva factorial n!,
distinta a la exhibida anteriormente
8.2. EJEMPLOS DE PROBLEMAS QUE PUEDEN RESOLVERSE RECURSIVAMENTE 123
f act(n) = f
entonces
f act N N
1, si n = 0;
(n)
n f act(n 1), en otro caso.
#include<iostream>
#include<cstdlib>
int main(){
int n;
cout << "n? = ";
cin >> n;
cout << "fact(n) = ";
cout << fact(n);
cout << "\n";
system("pause");
return EXIT_SUCCESS;
};
Como se van a formar parejas, el orden no importa. Una estrategia para encontrar el
numero de parejas puede ser el siguiente:
Simpsons =
, , ,
, , ,
C(4, 2)
, , , , ,
C(3, 1) + C(3, 2)
, , ,
C(3, 1)
, ,
, , ,
C(2, 0) = 1 + C(2, 1)
, ,
C(2, 1)
, , ,
C(1, 0) = 1 + C(1, 1) = 1
si se escoge a Bart, entonces ya se tiene otra pareja, si no entonces Lisa debe hacer
parte de la siguiente pareja.
, ,
C(3, 2)
,
, ,
C(2, 1) + C(2, 2) = 1
, ,
C(2, 1)
, , ,
C(1, 0) = 1 + C(1, 1) = 1
si se escoge a Bart, entonces ya se tiene otra pareja, si no entonces Lisa debe hacer
parte de la ultima pareja.
126 CAPITULO 8. FUNCIONES RECURSIVAS
, , ,
, , ,
C(n, k) = c
entonces
8.2. EJEMPLOS DE PROBLEMAS QUE PUEDEN RESOLVERSE RECURSIVAMENTE 127
C NNN
si k > n;
0,
(n, k) 1, si (k = 0) (n = k);
C(n 1, k 1) + C(n 1, k), en otro caso.
#include<iostream>
#include<cstdlib>
int main(){
int n;
int k;
cout << "n? = ";
cin >> n;
cout << "k? = ";
cin >> k;
cout << "C(n,k) = ";
cout << C(n,k);
cout << "\n";
system("pause");
return EXIT_SUCCESS;
};
mes1 . Cual es la cantidad de parejas de conejos en la isla una vez transcurrido un ano,
suponiendo que ningun conejo muere?.
Si fn denota la cantidad de parejas de conejos en el mes n, entonces, en el mes cero, en
este aun no se ha hecho la liberacion de la pareja de conejos, por lo tanto la cantidad de
parejas es f0 = 0.
n = 0, f0 = 0
Durante el primer mes, en este se hace la liberacion de la primera pareja de conejos, pero
aun no han alcanzado la edad para reproducirse, por lo tanto, no ha habido descendencia,
por lo tanto, f1 = 1.
n = 1, f1 = 1
Durante el segundo mes, ya haba una pareja de conejos del mes anterior y estos aun
no han alcanzado la edad para reproducirse, por lo tanto, no hubo descendencia, de donde
f2 es igual a la cantidad de conejos que haban en el mes anterior mas la descendencia que
produjeron las parejas de mas de dos meses, es decir, f2 = 1.
n = 2, f2 = f1 + f0 = 1 + 0 = 1
Durante el tercer mes, ya haba una pareja de conejos del mes anterior y durante el
transcurso de este mismo mes los conejos alcanzaron la madures para reproducirse, por lo
tanto hubo descendencia, de donde f3 es igual a la cantidad de conejos del mes anterior
mas la descendencia que se produjo en este mes, es decir, f3 = 2.
n = 3, f3 = f2 + f1 = 1 + 1 = 2 +
Durante el cuarto mes ya haban dos parejas de conejos del mes anterior, y la pareja
madura es la que haba en el segundo mes, por lo tanto, la descendencia fue generada
solo por esa pareja, de donde f4 es igual a la cantidad de parejas del mes anterior mas la
descendencia que genere la pareja del segundo mes, es decir, f4 = f3 + f2 = 2 + 1 = 3.
n = 4, f4 = f3 + f2 = 2 + 1 = 3 +
1
Este problema fue propuesto originalmente por el italiano Leonardo Pisano Bigollo (11701250), mas
conocido como Leonardo de Pisa o Fibonacci (que significa hijo de Bonacci, filius Bonacci ) en su libro
Liber abaci publicado en 1202.
8.2. EJEMPLOS DE PROBLEMAS QUE PUEDEN RESOLVERSE RECURSIVAMENTE 129
Durante el quinto mes ya haban tres parejas de conejos del mes anterior, y de estas hay
dos parejas maduras, que son las que haban en el tercer mes, por lo tanto, la descendencia
fue generada por esas dos parejas, de donde f5 es igual a la cantidad de parejas del mes
anterior mas la descendencia que generen las parejas del tercer mes, es decir, f5 = f4 + f3 =
3 + 2 = 5.
n = 5, f5 = f4 + f3 = 3 + 2 = 5 +
De aqu que, transcurrido el primer ano, en la isla habran 144 parejas de conejos.
A los numeros que son generados utilizando esta regla se les conoce como numeros de
Fibonacci.
A partir del analisis anterior, se puede disenar una funcion recursiva que permite cal-
cular cualquier numero de Fibonacci.
f ibo(n) = f
donde se tienen las variables
entonces
f ibo N N
si n = 0;
0,
(n) 1, si n = 1;
f ibo(n 1) + f ibo(n 2), en otro caso.
130 CAPITULO 8. FUNCIONES RECURSIVAS
#include<iostream>
#include<cstdlib>
int main(){
int n;
cout << "n? = ";
cin >> n;
cout << "Fibonacci(n) = ";
cout << fibo(n);
cout << "\n";
system("pause");
return EXIT_SUCCESS;
};
m=pq
donde p, q N, 1 < p < m y 1 < q < m. Entonces, para saber si un numero es primo es
equivalente a verificar que no es compuesto, es decir, que no hay un numero k N, tal que
1 < k < m y que k sea divisor de m.
De lo anterior, para saber si un numero n es compuesto hay que ir probando con los
numeros desde 2 hasta n 1, y observar si alguno de ellos es divisor de n; si no es as,
entonces n es primo.
Una observacion adicional que hara mas eficiente el algoritmo es la que se puede concluir
a partir del siguiente teorema
8.2. EJEMPLOS DE PROBLEMAS QUE PUEDEN RESOLVERSE RECURSIVAMENTE 131
A partir del teorema anterior, se pueden disenar las funciones que permiten determinar
si un numero es primo o no. Inicialmente es necesario construir una funcion auxiliar o
ayudante (en ingles helper ) que nos permita responder a la pregunta Dado un par de
enteros positivos n y d, n es multiplo de algun valor entre d y n inclusive?. La siguiente
funcion recursiva permite responder a la pregunta anterior.
multiplo(n, d) = valor
donde se establecen las variables
entonces
multiplo N P B
si n mod d = 0;
V,
(n, d) F, si d > n;
multiplo(n, d + 1), en otro caso.
Con el uso de la anterior funcion se puede disenar una nueva funcion que permita
determinar si un entero mayor que 1 es primo o no, la idea es probar los numeros entre 2
y n usando la funcion anterior y verificar si n es multiplo de alguno de estos numeros, si
se da este caso, entonces el numero no es primo, en caso contrario se tendra que el numero
es primo. La siguiente funcion permite determinar si un numero es primo o no
primo(n) = valor
entonces
primo N {0, 1} B
V, si n = 2;
(n)
multiplo(n, 2), en otro caso.
#include<iostream>
#include<cstdlib>
#include<cmath>
int main(){
int n;
cout << "n? = ";
cin >> n;
cout << "Es n primo? = ";
cout << primo(n);
cout << "\n";
system("pause");
return EXIT_SUCCESS;
};
multiplo N P B
n mod d = 0;
V, si
F, d > n;
(n, d)
si
d = 2;
multiplo(n, 3), si
multiplo(n, d + 2), en otro caso.
Pared 1
134 CAPITULO 8. FUNCIONES RECURSIVAS
p1
Pared 2
p2
El gerente de la empresa desea fijar unos carteles del mismo ancho, con la condicion de
que tiene que colocar los afiches completos, que abarquen en su totalidad dichas paredes y
que no se solapen. La empresa tiene la capacidad de mandar a imprimir y cortar los afiches
de cualquier ancho. Cual sera el afiche de mayor ancho que puede colocar la empresa de
tal manera que utilice en su totalidad las paredes y que los afiches se peguen completos
sin solaparse?
1. Para saber cual es el afiche mas ancho que se puede colocar en las paredes p1 y p2 ,
se debe observar que la pared mas corta es p2 , por lo tanto el afiche mas ancho debe
tener por mucho el ancho de esa pared.
2. Si a la pared mas ancha p1 se tapa con la pared mas corta p2 , se obtiene un resto r1
de pared como el siguiente
p1
p2 r1
3. Como los afiches taparan completa y exactamente la pared p2 , para que estos afiches
tambien tapen la pared p1 , entonces deben tapar completa y exactamente el resto r1
de la pared. Por lo que para este caso el afiche mas ancho debe tener por mucho el
ancho de ese resto r1 de pared.
4. El ancho de r1 pasa a ser entonces el candidato a ser el ancho del afiche, por lo que
es necesario que el afiche que tape la pared r1 tambien tape la pared p2 . As, si ahora
se tapa pared p2 con la pared r1 tantas veces como sea posible, entonces, se obtiene
un resto r2 de pared como el siguiente
p2
r1 r1 r2
8.2. EJEMPLOS DE PROBLEMAS QUE PUEDEN RESOLVERSE RECURSIVAMENTE 135
5. En este caso ocurre lo mismo que en el numeral 3, para tapar la pared p2 se debe
tapar tambien la pared restante r2 , por lo que el afiche mas ancho debe tener por
mucho el ancho de ese resto r2 de pared.
6. De lo anterior, se tiene que el ancho de r2 pasa a ser entonces el candidato a ser el
ancho del afiche, por lo que es necesario que el afiche que tape la pared r2 tambien
tape la pared restante r1 . As, si ahora se tapa pared r1 con la pared r2 tantas veces
como sea posible, entonces, se obtiene un resto r3 de pared como el siguiente
r1
r2 r3
7. En este punto, el analisis es similar a los casos anteriores, pues para tapar la pared
r1 es necesario tapar el resto de pared r3 . Con lo cual se obtiene un nuevo candidato,
el ancho de la pared r3 . Si con esta pared r3 se tapa la pared r2 tantas veces como
sea posible, entonces se obtiene el siguiente cubrimiento total de la pared r2 .
r2
r3 r3
8. Por la construccion anterior, se tiene que un afiche que utilice en su totalidad las
paredes y que se peguen completos sin solaparse esta dado por el ancho de la pared
r3 . Un afiche de este ancho sera el de mayor tamano pues siempre se escogio el de
mayor tamano posible para ir descartando las otras opciones.
9. El aspecto de las paredes con los afiches colocados de acuerdo al resultado obtenido
es el siguiente
la primera longitud mide l1 = 2 unidades y la segunda l2 = 2, no existe un segmento que
quepa un numero exacto de veces, a este tipo de medidas se les denomina inconmensura-
bles, y para las que s existe un segmento que cabe un numero exacto de veces se les llama
conmensurables.
Volviendo al problema de encontrar el afiche de mayor longitud que quepa en un par
de paredes de forma exacta sin solaparse, en el caso de que las paredes tengan longitudes
numeros naturales unidades, entonces en estas siempre es posible encontrar una longitud
que cumpla con las condiciones impuestas anteriormente, pues estas longitudes con con-
mensurables, ya que en el peor de los casos los afiches con longitud una (1) unidad siempre
cabra un numero exacto de veces sin solaparse.
En matematicas, a el segmento de mayor longitud en cabe un numero exacto de veces
en dos segmentos conmensurables se le conoce como el maximo comun divisor de los dos
segmentos.
A partir del analisis anterior, se puede disenar una funcion recursiva que permite cal-
cular el maximo comun divisor de dos numeros p y q, donde se supone que p q.
mcd recur(p, q) = m
donde se tienen las variables
entonces
mcd recur N N N
p, si q = 0;
(p, q)
mcd recur(q, p mod q), en otro caso.
Como se desea que se pueda calcular el maximo comun divisor de cualesquiera dos
numeros naturales, entonces la funcion anterior se utilizara como una funcion auxiliar
(helper ), y la siguiente funcion s permitira calcular el maximo comun divisor de cuales-
quiera dos numeros, esta lo que hace es primero encontrar el mayor de los dos numeros y
luego utilizar la funcion mcd recur(p, q) de forma correcta.
mcd(p, q) = m
donde se tienen las variables
entonces
mcd N N N
mcd recur(p, q), si p > q;
(p, q)
mcd recur(q, p), en otro caso.
Y la funcion
La codificacion en C++ de estas funciones junto con su programa principal es
#include<iostream>
#include<cstdlib>
int main(){
int p;
int q;
cout << "p? = ";
cin >> p;
cout << "q? = ";
cin >> q;
cout << "m.c.d(p,q) = ";
cout << mcd(p,q);
cout << "\n";
system("pause");
return EXIT_SUCCESS;
};
138 CAPITULO 8. FUNCIONES RECURSIVAS
8.4. Ejercicios
1. Modele mediante una funcion matematica y disene un programa recursivo que de-
termine el mayor de dos numeros enteros no negativos que utilice solo el operador de
comparacion de la igualdad (==), la funcion sucesor (sumar 1), la funcion predecesor
(restar 1) y la estructura condicional (if, if-else).
2. Modele mediante una funcion matematica y disene un programa recursivo que calcule
la suma de los primeros n numeros positivos ni=1 i.
3. Modele mediante una funcion matematica y disene un programa recursivo que calcule
la suma de los cuadrados de los primeros n numeros positivos ni=1 i2 .
4. Modele mediante una funcion matematica y disene un programa recursivo que calcule
el producto de los cuadrados de los primeros n numeros positivos ni=1 i2 .
5. Modele mediante una funcion matematica y disene un programa recursivo que calcule
el logaritmo entero en base 2 de n log2 n. Por ejemplo, log2 1 = 0, log2 4 = 2,
log2 7 = 2, log2 15 = 3.
6. Modele mediante una funcion matematica y disene un programa recursivo que calcule
el logaritmo entero en base b de n logb n.
7. Modele mediante una funcion matematica
y disene un programa
recursivo calcule
que
laraz cuadrada entera de a a. Por ejemplo, 0 = 0, 1 = 1, 5 = 2,
10 = 3.
8. Modele mediante una funcion matematica y disene un programa recursivo que calcule
la raz n-esima entera de a a.
n
9. Modele mediante una funcion matematica y disene un programa recursivo que calcule
la funcion modulo (m mod n = k). Por ejemplo, 0 mod 2 = 0, 4 mod 2 = 0, 3 mod 3 = 0,
10 mod 3 = 1, 14 mod 5 = 4.
10. Modele mediante una funcion matematica y disene un programa recursivo que de-
termine la cantidad de dgitos que componen un numero natural n. Por ejemplo,
longitud(654321) = 6.
11. Modele mediante una funcion matematica y disene un programa recursivo que in-
vierta la cifras de un numero n dado. Por ejemplo, inversa(654321) = 123456.
12. Modele mediante una funcion matematica y disene un programa recursivo que de-
termine si un numero es palndromo. Un numero se dice palndromo si al leerlo de
izquierda a derecha es lo mismo que leerlo de derecha a izquierda. Por ejemplo,
palindromo(1) = V , palindromo(1234321) = V , palindromo(123421) = F .
13. Modele mediante una funcion matematica y disene un programa recursivo que
calcule el mnimo comun multiplo de dos numeros positivos a y b. Por ejemplo,
mcm(18, 24) = 72.
140 CAPITULO 8. FUNCIONES RECURSIVAS
14. Modele mediante una funcion matematica y disene un programa que dados dos
numero positivos p y q, donde p representa el numerador y q el denominador de la
p p
fraccion , imprima primero el numerador de la fraccion simplificada a su mnima
q q
p
expresion y luego el denominador de la fraccion simplificada a su mnima expresion.
q
15. Modele mediante una funcion matematica y disene un programa que dados cuatro
numero positivos p, q, r y s, donde p representa el numerador y q el denominador
p
de la fraccion , y r representa el numerador y s el denominador de la fraccion
q
, imprima primero el numerador de la fraccion resultante de la operacion +
r p r
s q s
simplificada a su mnima expresion y luego el denominador de la fraccion resultante
de la operacion + simplificada a su mnima expresion.
p r
q s
Captulo 9
Estructuras de programacion cclicas
El ciclo while permite ejecutar un bloque de instrucciones mientras que una expresion
booleana dada se cumpla, es decir, mientras su evaluacion de como resultado verdadero.
La expresion booleana se denomina condicion de parada y siempre se evalua antes de
ejecutar el bloque de instrucciones. Si la condicion no se cumple, el bloque no se ejecuta.
Si la condicion se cumple, el bloque se ejecuta, despues de lo cual la instruccion vuelve a
empezar, es decir, la condicion se vuelve a evaluar.
En el caso en que la condicion se evalue la primera vez como falsa, el bloque de instruc-
ciones no sera ejecutado, lo cual quiere decir que el numero de repeticiones o iteraciones
de este bloque sera cero. Si la condicion siempre evalua a verdadero, la instruccion se
ejecutara indefinidamente, es decir, un numero infinito de veces.
La sintaxis general de un ciclo while es la siguiente
<init>
while(<cond>){
<body>
<update>
};
en donde:
El fragmento <cond> es la condicion de parada que se evalua cada vez que se inicia
el ciclo.
141
142 CAPITULO 9. ESTRUCTURAS DE PROGRAMACION CICLICAS
El fragmento <update> es el bloque que se utiliza para actualizar las variables que
son utilizadas para evaluar la condicion de parada cuando se intenta reiniciar el ciclo.
Ejemplo. Para el siguiente fragmento de codigo que contiene un ciclo while
int i = 0;
while(i <= 5){
cout << i;
cout << endl;
i = i + 1;
};
cuando se ejecuta este ciclo lo que se obtiene en la consola de salida es el texto que se
presenta en el cuadro a la derecha
int i = 0; 0
while(i <= 5){ 1
cout << i; 2
cout << endl; 3
i = i + 1; 4
}; 5
int i = 1;
int j = 10;
while(i < j){
cout << i;
cout << " ";
cout << j;
cout << endl;
i = i * 2;
j = j + 10;
};
int i = 1;
int j = 10;
while(i < j){ 1 10
cout << i; 2 20
cout << " "; 4 30
cout << j; 8 40
cout << endl; 16 50
i = i * 2; 32 60
j = j + 10; 64 70
};
Observese que las variables i y j terminan el ciclo con los valores 128 y 80, y como 128
no es menor que 80, entonces el ciclo se para, por esta razon no se imprimen estos valores.
Para encontrar dicho numero hay un algoritmo muy sencillo que permite encontrar el
valor.
144 CAPITULO 9. ESTRUCTURAS DE PROGRAMACION CICLICAS
El algoritmo consiste en calcular los terminos de una progresion geometrica que inicia
con el termino x0 = 1 y para la cual los terminos siguientes se calculan utilizando la razon
de la progresion r = 12, es decir, xn+1 =
xn
, esto se realiza mientras cada nuevo termino
2
es positivo.
La codificacion en C++ de una funcion que permite hallar el mnimo numero positivo
representable en la maquina junto con su programa principal es
#include<iostream>
#include<cstdlib>
double min_maquina(){
double Xo = 1.0;
double Xi = Xo / 2;
while(Xi > 0.0){
Xo = Xi;
Xi = Xo / 2.0;
};
return Xo;
};
Ahora, dentro del ciclo la variable Xo jugara el rol del termino xn+1 mediante la
asignacion Xo = Xi;.
Las dos ultimas rutinas descritas se realizan mientras el valor de la variable Xi sea
mayor a 0.
int main(){
cout << "El numero positivo mas pequeno que se puede\n";
cout << "representar en la maquina es: ";
cout << min_maquina();
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
<init>
while(<cond>){
<body>
<update>
};
estas dos funciones son equivalentes, ya que ejecutan las mismas modificaciones de las
variables, pues se tiene que el fragmento de codigo:
En la construccion de estas funciones aparecen dos variable que tienen una connotacion
muy importante:
La variable i juega el rol de una variable contadora ya que permite llevar el conteo
de cuantos ciclos se han efectuado.
La codificacion en C++ de una funcion que permite sumar los primeros n numeros
naturales positivos junto con su programa principal es
9.2. LA ESTRUCTURA DE CONTROL DE CICLOS PARA (FOR) 147
#include<iostream>
#include<cstdlib>
int main(){
int n;
cout << "n? = ";
cin >> n;
cout << "La suma de los primeros n numeros es: ";
cout << suma(n);
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
n? = 6
La suma de los primeros n numeros es: 21
Presione una tecla para continuar . . .
i=1 2
la cual se puede demostrar por induccion matematica o se puede generalizar a partir de
la observacion de las siguientes figuras
Al sumar los numeros del 1 al 6 se puede construir una escalera de cuadrados des-
cendente empezando por un cuadrado y terminando con seis cuadrados, como la que se
muestra a continuacion,
148 CAPITULO 9. ESTRUCTURAS DE PROGRAMACION CICLICAS
1
2
3
4
5
6
1 1
2 2
3 3
4 4
5 5
6 6
ahora, si se rota la segunda escalera dos angulos rectos se obtienen las siguientes figuras
1 6
2 5
3 4
4 3
5 2
6 1
1 + 6 = 7 +
2 + 5 = 7 +
3 + 4 = 7 +
4 + 3 = 7 +
5 + 2 = 7 +
6 + 1 = 7 +
como se observa a continuacion, siempre se puede formar un rectangulo tal que uno de sus
lados es igual a n = 6 y el otro es igual a n + 1 = 7, y por la forma en que se construyo el
rectangulo se observa que la suma de los cuadrados de cada escalera es igual a la mitad
de la cantidad total de cuadrados en el rectangulo.
9.3. LA ESTRUCTURA DE CONTROL DE CICLOS HACER-MIENTRAS (DO) 149
1 + 6 = 7
2 + 5 = 7
=
n=6
3 + 4 7
4 + 3 = 7
5 + 2 = 7
6 + 1 = 7
42
n+1=7
6(6 + 1) 6 7 42
1 + 2 + 3 + 4 + 5 + 6 = i = = = = 21
6
i=1 2 2 2
Existe otra estructura cclica en programacion, esta se conoce como un ciclo do. Esta
estructura es casi equivalente a la estructura while, ya que usualmente se utiliza cuando
con seguridad y de forma anticipada se sabe que se hara al menos una evaluacion del bloque
principal del ciclo. En esta estructura cclica la verificacion de la condicion de parada se
realiza al final del ciclo.
Dada la sintaxis general de un ciclo while
<init>
while(<cond>){
<body>
<update>
};
<init>
do{
<body>
<update>
}while(<cond>);
150 CAPITULO 9. ESTRUCTURAS DE PROGRAMACION CICLICAS
En segunda instancia, por la ley de tricotoma de los numeros reales, se cumple que:
x0 = a x0 > a x0 < a
x0 = a=
0 a
x0
Si x0 > a entonces
x0 > a
x0 a > a a
x0 a > a
a>
a
x0
de donde x0 > a> .
a
x0
( )
a x0
0 a
x0
Si x0 < a entonces
x0 < a
x0 a < a a
x0 a < a
a<
a
x0
de donde x0 < a< .
a
x0
( )
x0 a
0 a
x0
a
Como se observa en el analisis anterior, la relacion de a con x0 y , es que a
x0
siempre o es igual a esos valores (primer caso) o esta entre esos valores (segundo y
tercer caso).
152 CAPITULO 9. ESTRUCTURAS DE PROGRAMACION CICLICAS
a
Si a es igual a x0 y , entonces el problema ya se soluciono y se tiene el valor
x0
exacto de a.
a
Si a esta entre x0 y , entonces hay que decidir si alguno de esos valores es una
x0
aproximacion lo suficientemente exacta a a, o si una combinacion esos valores es
una aproximacion lo suficientemente exactaa a, o si es necesario calcular valores
que se aproximen mejor al valor exacto de a.
Si es necesario calcular valores que se aproximen mejor al valor exacto de a, puede
a
observarse que como a esta entre x0 y , entonces el punto medio del intervalo
x0
que determinan esos valores 12 x0 + xa0 es un valor que tambien sirve de aproximacion
al valor de a, porlo tanto ese valor se puede tomar como una nueva aproximacion
inicial al valor de a.
Una pregunta que hay que hacerse en este momento es hasta cuando se deben
calcular nuevos valores?.
Una de las caractersticas de estos metodos constructivistas es que es posible que
no se obtenga el valor exacto porque el resultado no se puede representar con finita
memoria o es demasiado grande para la memoria o el tiempo necesario para calcular
el valor exacto es infinito.
Para este ejemplo y muchos de este tipo, hay que conformarse con obtener una
aproximacion lo suficientemente precisa que sea util para resolver el problema que
se esta solucionado.
Para decidir cuando se tiene una aproximacion lo suficientemente precisa de la so-
lucion, el metodo mas sencillo que se suele utilizar es detenerse cuando la distancia
entre dos aproximaciones seguidas es lo suficientemente pequena con respecto a un
9.3. LA ESTRUCTURA DE CONTROL DE CICLOS HACER-MIENTRAS (DO) 153
valor dado, lo que se suele denominar la precision del error y se denota por el
smbolo ". A la distancia entre las dos aproximaciones se les llama el error absoluto
y normalmente se calculan nuevas aproximaciones hasta que el error absoluto sea
menor que ", lo que se expresa como
xi1 xi
( ( ( ) ) )
0 a
<"
xi1 xi+1 xi
( ( ( ) ) )
0 a
La codificacion en C++ de una funcion que permite calcular la raz cuadrada de cual-
quier numero real positivo junto con su programa principal es
#include<iostream>
#include<cstdlib>
La funcion valor absoluto es necesaria para calcular la distancia entre dos valores.
Como para calcular el error relativo es necesario tener al menos dos aproximaciones, en-
tonces, dado el primer valor inicial es necesario calcular al menos otro valor de la sucesion,
razon por la cual el uso de un ciclo do es muy conveniente.
154 CAPITULO 9. ESTRUCTURAS DE PROGRAMACION CICLICAS
int main(){
double a;
cout << "a? = ";
cin >> a;
cout << "Una aproximacion de la raiz cuadrada de a es: ";
cout << raiz(a);
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
a? = 2
Una aproximacion de la raiz cuadrada de a es: 1.41421
Presione una tecla para continuar . . .
El valor 1.41421 es una aproximacion al valor 2 con una precision del error menor a
4
10 .
El metodo anterior es equivalente al metodo de biseccion y el de Newton para hallar
races de funciones.
9.4. SIMULACION DE CICLOS USANDO FUNCIONES RECURSIVAS 155
<init>
while(<cond>){
<body>
<update>
};
1. Se debe crear una nueva funcion recHelperFunc() que tendra tantos parametros
como variables intervengan en el ciclo while a simular;
2. La variable principal que se desea calcular con el ciclo se debe colocar como primer
parametro de la funcion.
4. Dentro del condicional se anexan las instrucciones del <body> y luego las del
<update>.
6. Finalmente se retorna la variable principal que se desea calcular con el ciclo inme-
diatamente despues de finalizar el condicional.
7. La porcion del codigo que abarca el ciclo while se reemplaza por una asignacion donde
a la variable principal que se desea calcular con el ciclo se le asigna el resultado de
evaluar la funcion recursiva en las variables que intervienen en el ciclo y que fueron
inicializadas previamente al ciclo.
<init>
while(<cond>){
<body>
<update>
};
<init>
var1 = recHelperFunc(var1, var2, ... , varN);
La funcion original sera modificada eliminando el ciclo while sin eliminar el bloque
<init> y reemplazandola por la instruccion donde se llama la funcion recursiva con las
variables que intervienen en el ciclo original y se asigna el valor final de la evaluacion de
la funcion recursiva a la variable fact que se deseaba calcular en el ciclo. El aspecto de la
funcion original modificada como se explico anteriormente es el siguiente.
teclado, se verifica si se incumple con alguna de las condiciones que deben cumplir las
variables, en caso de que se incumpla, se solicita de nuevo al usuario que vuelva a ingresar
la informacion y esto se hace hasta que la informacion ingresada sea correcta.
Ejemplo. Con respecto al algoritmo para el calculo del area de un rectangulo dada la
definicion del tipo de dato podran estarse leyendo largos o anchos negativos. La notacion
matematica tambien permite restringir el dominio y el rango de los conjuntos quedando
la funcion de la siguiente forma
#include<iostream>
#include<cstdlib>
int main(){
double largo;
double ancho;
do{
cout << "Por favor ingrese el largo del rectangulo" << endl;
cout << "largo? = ";
cin >> largo;
}while(largo < 0);
do{
cout << "Por favor ingrese el ancho del rectangulo" << endl;
cout << "ancho? = ";
cin >> ancho;
}while(ancho < 0);
cout << "El area del rectangulo es: ";
cout << area_rectangulo(largo, ancho);
cout << endl;
system("pause");
return EXIT_SUCCESS;
};
160 CAPITULO 9. ESTRUCTURAS DE PROGRAMACION CICLICAS
9.7. Ejercicios
1. Imprimir un listado con los numeros del 1 al 100 cada uno con su respectivo cuadrado.
2. Imprimir un listado con los numeros impares desde 1 hasta 999 y seguidamente otro
listado con los numeros pares desde 2 hasta 1000.
3. Imprimir los numeros pares en forma descendente hasta 2 que son menores o iguales
a un numero natural n 2 dado.
5. Imprimir los numeros de 1 hasta un numero natural n dado, cada uno con su res-
pectivo factorial.
9. Elaborar una funcion que reciba un numero entero, que retorne 1 si el numero es
negativo, si el numero es positivo debe devolver una clave calculada de la siguiente
manera: se suma cada dgito que compone el numero y a esa suma se le calcula el
modulo 7. Por ejemplo: para la cifra 513, la clave sera 5 + 1 + 3 = 9; 9 mod 7 = 2.
11. Introducir un rango especificado por 2 numeros enteros, tal que el primero sea menor
al segundo y contar el numero de multiplos de un numero entero ledo que existe en
el rango. Por ejemplo, si se introduce 2 y 21, el numero de multiplos de 3 es 7, dado
que 3, 6, 9, 12, 15, 18 y 21 son multiplos de 3 en el rango [2, 21].
12. Disenar una funcion que permita calcular una aproximacion de la funcion exponencial
alrededor de 0 para cualquier valor x R, utilizando los primeros n terminos de la
serie de Maclaurin
exp(x, n) .
n
xi
i=0 i!
13. Disenar una funcion que permita calcular una aproximacion de la funcion seno alre-
dedor de 0 para cualquier valor x R (x dado en radianes), utilizando los primeros
n terminos de la serie de Maclaurin
(1)i x2i+1
sen(x, n)
n
14. Disenar una funcion que permita calcular una aproximacion de la funcion coseno
alrededor de 0 para cualquier valor x R (x dado en radianes), utilizando los primeros
n terminos de la serie de Maclaurin
(1)i x2i
cos(x, n)
n
(2i)!
.
i=0
15. Disenar una funcion que permita calcular una aproximacion de la funcion logaritmo
natural alrededor de 0 para cualquier valor x R+ , utilizando los primeros n terminos
de la serie de Maclaurin
1 x2 1
2i+1
ln(x, n)
n
i=0 2i + 1 x + 1
2
.
16. Disenar una funcion que permita calcular una aproximacion de la funcion arco tan-
gente para cualquier valor x [1, 1], utilizando los primeros n terminos de la serie
de Maclaurin (al evaluar esta funcion el resultado que se obtiene esta expresado en
radianes)
(1)i x2i+1
arctan(x, n)
n
i=0 (2i + 1)
.
162 CAPITULO 9. ESTRUCTURAS DE PROGRAMACION CICLICAS
Captulo 10
Vectores o arreglos unidimensionales
v = (v1 , v2 , v3 , . . . , vn )
donde el vector esta constituido por n componentes de un conjunto generico V. Si v Vn ,
entonces el vector se dice que es n-dimensional o de tamano n.
Ejemplo. El siguiente vector de tamano 6 pertenece a Z6 y tiene una notacion particular
la cual es 06
06 = (0, 0, 0, 0, 0, 0)
En un vector, para referirse a una componente en particular, a esta se le dice que es
la componente en la posicion i o la i-esima componente, esto significa que el objeto es
la componente ubicada en la posicion i, se denota por la expresion vi y se puede ubicar
dentro del vector como se muestra a continuacion
componente i-esima
(v1 , . . . , vi , . . . , vn )
163
164 CAPITULO 10. VECTORES O ARREGLOS UNIDIMENSIONALES
v1 = 1. v2 = 34 . v3 = 0.25.
v4 = 15 . v5 = 2. v6 = 0.0.
v7 = . v8 = 3 5. v9 = 0.9.
Vn = V V V V
n-veces
se puede obtener el conjunto de los vectores V , el cual se define como la union de todos
los productos cartesianos del conjunto V, de la siguiente manera
V = Vn
nN
as, el conjunto de los arreglos del tipo de datos T es una coleccion de variables del tipo
de datos T.
Para definir arreglos se utilizara la notacion de memoria dinamica, es decir, si x T
entonces el vector x se creara en tiempo de ejecucion del programa.
Si se quiere expresar en C++ que x T esto se escribe como T* x; y para reservar el
espacio de memoria para todo el arreglo de tipo T, esto se escribe como x = new T[n].
De donde, para crear un arreglo x de tamano n y de tipo T se utiliza la instruccion
10.2. LOS ARREGLOS O VECTORES EN COMPUTACION 165
T* x = new T[n]
Con esta instruccion se reserva una porcion de la memoria M que es utilizada para
almacenar el arreglo y que es bloqueada para que solo se pueda utilizar para guardar
valores en el arreglo, a menos que el espacio se libere y se pueda utilizar para almacenar
otro tipo de informacion. A la porcion de espacio de memoria que ocupa un arreglo x lo
notaremos como Mx . Graficamente esto se puede ver as:
new T[n]
T T T T
Mx
T* x = new T[n]
T T T T
x Mx
166 CAPITULO 10. VECTORES O ARREGLOS UNIDIMENSIONALES
xi x[i-1]
( x1 , x2 , x3 , , xn1 , xn)
En lenguajes como SciLab y MatLab, la primera componente del arreglo esta ubicada
en la posicion 1, y para un arreglo de tamano n se tiene que la ultima componente del
arreglo estara ubicada en la posicion n, por lo que las posiciones se manejan como en
notacion matematica de vectores, es decir, para acceder en SciLab o MatLab a la variable
almacenada en la componente i se utiliza la equivalencia
10.2. LOS ARREGLOS O VECTORES EN COMPUTACION 167
xi x[i]
En caso de que se quiera acceder a una componente mayor o igual a la n-esima en C++
entonces el valor almacenado sera lo que en ese momento tenga la memoria en el siguiente
campo de la memoria, pero este sera un valor inesperado, por que simplemente no se ha
protegido ese espacio de memoria y la informacion all es desconocida a priori. Si se quiere
acceder a una componente menor a 0, ocurre algo similar a lo descrito anteriormente.
crear arreglo T N T
(n) x, donde x Tn T
En C++ se traduce
T* crear_arreglo_T(int n){
return new T[n];
};
Para eliminar un arreglo, se debe entender que lo que ocurre es que la porcion del
espacio de la memoria que se utiliza para almacenar las componentes del arreglo se liberan
o se regresan al sistema operativo para que este disponga de esa memoria para almacenar
nueva informacion.
168 CAPITULO 10. VECTORES O ARREGLOS UNIDIMENSIONALES
Matematicamente se puede modelar esto como una funcion que dado el arreglo x y el
tamano del arreglo n (aunque este ultimo no se requiere, pero se suele utilizar), se retorna
la porcion del espacio de la memoria Mx que es utilizado para almacenar el arreglo x, de
esta manera la funcion se puede escribir as
Hay que recordar aqu que (M) es el conjunto de todos los subconjuntos de la memoria
Para traducir esta funcion a C++ se debe tener en cuenta que la funcion no retorna un
valor de un tipo de datos, si no que se regresa memoria al sistema operativo, por lo que la
funcion regresa un espacio que esta vacio y queda disponible para utilizarse de nuevo.
El desbloqueo de la memoria y la liberacion del espacio utilizado por el arreglo x se
escribe en C++ mediante la instruccion
delete[] x;
T T T T
x Mx
delete[] x;
Para decir que se retorna memoria vaca al sistema operativo se utiliza como tipo de
dato el vaco que en C++ se escribe como void y en el cuerpo de la funcion se utiliza la
10.3. ARREGLOS Y FLUJOS DE DATOS 169
instruccion return; para indicar que se retorno una porcion de espacio que esta vacio y
que queda disponible para usarse de nuevo.
Una funcion que solo manipula la memoria y que retorna un tipo de dato vaco, en
programacion se conoce como un procedimiento.
De esta manera, la traduccion de la funcion en C++ se escribe de la siguiente manera
leer arreglo T IS T N T
(is, x, n) x, donde xi = leer T(is),
i = 1, 2, 3, . . . , n.
Ejemplo. En C++ para leer un arreglo de tipo caracter se utiliza la siguiente funcion
1 2
a a
e e
i i a
u o n=5 u o n = 5, i=0
3 4
e i
i o
o a e u a e i
u n = 5, i=1 n = 5, i=2
5 6
o u
u
a e i o a e i o u
n = 5, i=3 n = 5, i=4
a e i o u
n = 5, i=5
escribir arreglo T OS T N OS
(os, x, n) os, donde escribir T(xi , os),
i = 1, 2, 3, . . . , n.
Ejemplo. En C++ para escribir un arreglo de tipo caracter se utiliza la siguiente funcion
1 2
n=5 n = 5, i = 0
a e i o u a e i o u
a
3 4
n = 5, i = 0 n = 5, i = 1
a e i o u a e i o u
a e a
172 CAPITULO 10. VECTORES O ARREGLOS UNIDIMENSIONALES
5 6
n = 5, i = 1 n = 5, i = 2
a e i o u a e i o u
a
e a i e
7 8
n = 5, i = 2 n = 5, i = 3
a e i o u a a e i o u a
e
i e o i
9 10
n = 5, i = 3 n = 5, i = 4
a e i o u a e a e i o u a e
i
o i u o
11 12
n = 5, i = 4 n = 5, i = 5
a a
a e i o u e i a e i o u e i
u o u o
13
a e i o u a e i o u
Es posible utilizar lo visto en funciones para realizar diversidad de calculos que involu-
cren arreglos.
Ejemplo. El cubo de las componentes de arreglos numericos enteros
10.3. ARREGLOS Y FLUJOS DE DATOS 173
Suponga que un archivo contiene unos datos numericos enteros tales que consta de 5
datos que se encuentran separados por una tabulacion as como se muestra a continuacion
1 2 3 4 5
Una funcion general que permite construir un nuevo arreglo que contiene el cubo de
cada componente de un arreglo dado es
cubo arreglo Z N Z
(x, n) y, donde yi = x3i ,
i = 1, 2, . . . , n.
#include<iostream>
#include<cstdlib>
#include<fstream>
int main(){
int n = 5;
ifstream ifs("arreglo_numeros.txt");
ofstream ofs("arreglo_cubos.txt");
int* x = crear_arreglo_int(n);
x = leer_arreglo_int(ifs, x, n);
int* y = cubo_arreglo(x, n);
escribir_arreglo_int(ofs, y, n);
liberar_arreglo_int(x, n);
liberar_arreglo_int(y, n);
ifs.close();
ofs.close();
cout << "El calculo del arreglo fue exitoso" << endl;
system("pause");
return EXIT_SUCCESS;
};
1 8 27 64 125
Una funcion recursiva que permite tambien calcular el cubo de las componentes de un
arreglo mediante la creacion de un nuevo arreglo que almacene el resultado del calculo, y
una funcion ayudante o auxiliar donde se realiza el calculo componente a componente y
se hacen los llamados recursivos para recorrer el arreglo original. Estas funciones pueden
ser escritas de la siguiente manera:
Una posible definicion teniendo en cuenta las observaciones anteriores y que el segundo
parametro de la funcion representa la longitud del arreglo se presenta a continuacion
suma arreglo R N R
x1 , si n = 1;
(x, n)
suma arreglo(x, n 1) + xn , en otro caso.
Una funcion en C++ que calcula la suma de las componentes de un arreglo, que esta es-
crita usando estructuras cclicas y que resulta ser equivalente a la anterior es la siguiente
176 CAPITULO 10. VECTORES O ARREGLOS UNIDIMENSIONALES
promedio R N R
(x, n) suma arreglo(x, n)n;
Una funcion en C++ que permite calcular el promedio de los datos numericos almace-
nados en un arreglo de longitud n es
esta ordenado R N B
si n = 1;
V,
(x, n) F, si xn1 > xn ;
esta ordenado(x, n 1), en otro caso.
10.3. ARREGLOS Y FLUJOS DE DATOS 177
Si el arreglo tiene una unica componente, entonces el maximo del arreglo es igual al
valor de esa componente.
max arreglo R N R
x1 , si n = 1;
M, donde M = max arreglo(x, n 1)
(x, n)
(M > xn );
xn , en otro caso.
Una funcion en C++ que permite calcular el maximo de un arreglo, que esta escrita
usando estructuras cclicas y que resulta ser equivalente a la anterior es la siguiente
Si el arreglo tiene mas de una componente, entonces, la posicion del maximo se ob-
tiene calculando la posicion del maximo del subarreglo que no contiene la ultima
componente del arreglo original y si al comparar esa componente con ultima compo-
nente del arreglo original, entonces la posicion del mayor sera la posicion del maximo
del arreglo original.
La codificacion en C++ de una funcion que permite obtener la posicion del maximo de
un arreglo de longitud n se presenta a continuacion
pos max R N N
1, si n = 1;
k, donde k = pos max(x, n 1)
(x, n)
xk > xn ;
n, en otro caso.
La codificacion en C++ de una funcion que permite obtener la posicion del maximo de
un arreglo de longitud n se presenta a continuacion.
Una funcion en C++ permite obtener la posicion del maximo de un arreglo, que esta es-
crita usando estructuras cclicas y que resulta ser equivalente a la anterior es la siguiente
La codificacion en C++ de una funcion que permite obtener un arreglo ordenado as-
cendentemente a partir de un arreglo dado de longitud n se presenta a continuacion.
Esta funcion hace un llamado a la funcion que permite obtener la posicion del maximo
de un arreglo dado y este se utiliza para intercambiar el elemento mayor a la ultima
posicion, para realizar esto es necesario utilizar una variable adicional o auxiliar t que
se utiliza para almacenar momentaneamente el valor de una de las componentes mientras
esta cambia su valor por el de la otra componente, y el valor de la otra componente cambia
al valor almacenado en la variable t. Este procedimiento muy comun al ordenar arreglos
se conoce en programacion como un swap de variables.
ordenar R N R
si n = 1;
x,
(x, n) ordenar(x, n 1), donde k = pos max(x, n)
(t = xk ) (xk = xn ) (xn = t).
La codificacion en C++ de una funcion que permite obtener un arreglo ordenado as-
cendentemente a partir de un arreglo dado de longitud n se presenta a continuacion.
10.3. ARREGLOS Y FLUJOS DE DATOS 181
Ejercicios
Nota: para todos los ejercicios que se solicita se solucionen a continuacion, la lectura
de los arreglos se deben hacer a partir de un archivo de entrada y si la salida es un arreglo,
este debe ser escrito en un archivo de salida.
S2 = (xi x)2
1 n
n 1 i=1
v = (v1 , v2 , . . . , vn )
9. Modele mediante una funcion matematica y desarrolle un algoritmo en C++ que cal-
cule la suma de dos vectores de numeros reales de igual tamano. Sean
v = (v1 , v2 , . . . , vn ) y w = (w1 , w2 , . . . , wn ) dos vectores, la suma de v y w (nota-
do v + w) es el vector dado por la expresion
v + w = (v1 + w1 , v2 + w2 , . . . , vn + wn )
10.3. ARREGLOS Y FLUJOS DE DATOS 183
10. Modele mediante una funcion matematica y desarrolle un algoritmo en C++ que cal-
cule la resta de dos vectores de numeros reales de igual tamano. Sean
v = (v1 , v2 , . . . , vn ) y w = (w1 , w2 , . . . , wn ) dos vectores, la resta de v y w (notado
v w) es el vector dado por la expresion
v w = (v1 w1 , v2 w2 , . . . , vn wn )
11. Modele mediante una funcion matematica y desarrolle un algoritmo en C++ que
calcule el producto punto de dos vectores de numeros reales de igual tamano. Sean
v = (v1 , v2 , . . . , vn ) y w = (w1 , w2 , . . . , wn ) dos vectores, el producto punto de v y w
(notado v w) es el numero dado por la expresion
v w = vi w i = v1 w 1 + v2 w 2 + + vn w n
n
i=1
12. Modele mediante una funcion matematica y desarrolle un algoritmo en C++ que cal-
cule el producto directo de dos vectores de reales de igual tamano. Sean
v = (v1 , v2 , . . . , vn ) y w = (w1 , w2 , . . . , wn ) dos vectores, el producto directo de v
y w (notado v w) es el vector dado por la expresion
v w = (v1 w1 , v2 w2 , . . . , vn wn )
14. Hacer un algoritmo que deje al final de un arreglo de numeros enteros todos los ceros
que aparezcan en dicho arreglo.
Ejemplo.
Ejemplo.
arreglo original: [0, 11, 36, 10, 0, 17, -23, 81, 0, 0, 12, 11, 0]
arreglo salida: [11, 36, 10, 17, -23, 81, 12, 11, 0, 0, 0, 0, 0]
15. Suponga que un arreglo de enteros esta lleno de unos y ceros y que el arreglo re-
presenta un numero binario al reves. Hacer un algoritmo que calcule los numeros en
base decimal que representa dicho arreglo de unos y ceros.
Ejemplo.
184 CAPITULO 10. VECTORES O ARREGLOS UNIDIMENSIONALES
Ejemplo.
16. Hacer un algoritmo que dado un numero entero no negativo, cree un arreglo de unos
y ceros que representa el numero en binario al reves.
Ejemplo.
numero: 389.
arreglo: [1, 0, 0, 1, 0, 1, 1, 1, 1], que representa el numero 111101001.
Ejemplo.
numero: 106.
arreglo: [0, 1, 0, 1, 0, 1, 1], que representa el numero 1101010.
17. Hacer un algoritmo que calcule el maximo comun divisor para un arreglo de enteros
positivos.
Ejemplo.
18. Hacer un algoritmo que calcule el mnimo comun multiplo para un arreglo de enteros
positivos.
Ejemplo.
Hasta ahora se ha trabajado con tipos de datos primitivos y arreglos. Entre los tipos
de datos primitivos se encuentran los caracteres que se definieron matematicamente como
el conjunto ASCII.
Los caracteres ASCII (American Standard Code for Information Interchange) permi-
ten representar letras, numeros, smbolos de agrupacion, los otros smbolos del teclado y
otros smbolos no visibles.
En un principio se usaron 7 bits para representar los caracteres ASCII con los cuales
se pueden representar 128 diferentes caracteres, y posteriormente se extendieron a 8 bits
185
186 CAPITULO 11. CADENAS DE CARACTERES
con los cuales se pueden representar 256 diferentes caracteres. La tabla completa de todos
los smbolos del conjunto ASCII extendido fueron presentados en la seccion 4.2.4.
Para especificar que x ASCII, en C++ se escribe
char x;
para inicializar un caracter se pueden utilizar los literales de caracter, estos son los carac-
teres entre comillas simples.
Ejemplo.
Comparacion de caracteres.
Ejemplo.
Como se vio en la seccion 4.2.4, existen tambien caracteres especiales, para los cuales
se puede conocer su codigo ASCII haciendo una conversion de caracter a entero, de la
siguiente manera.
Ejemplo.
h o l a m u n d o \0
0 1 2 3 4 5 6 7 8 9 10
int n = 10;
char* texto = new char[n];
texto[0] = h;
texto[1] = o;
texto[2] = l;
texto[3] = a;
texto[4] = \t;
texto[5] = \0;
cout << texto;
h o l a \t \0 ?? ?? ?? ??
0 1 2 3 4 5 6 7 8 9
Ejemplo. En la tabla 11.1 se presentan las longitudes maximas para nombrar archivos
en distintos sistemas operativos, en la longitud no se tiene en cuenta el smbolo de fin de
cadena, as que el arreglo de caracteres base esta definido con un tamano mas uno (+1)
del que se presenta en la tabla 11.1.
Las funciones de creacion permiten construir una cadena de forma generica con base en
lo que se explico en la seccion anterior y en la seccion 10.2.1.1 donde se presento la forma
11.3. FUNCIONES GENERALES SOBRE CADENAS 189
Sistema Longitud
Descripcion
operativo de cadena
Unix/Linux 255
MS-DOS 12 8 para el nombre, 3 para la extension y 1 para el punto.
Windows 260 Cuando hay que especificar el disco de origen (ej. C:\) se
necesitan 3 caracteres, entonces el maximo del nombre y
su ruta completa se reducen a 257.
Mac OS X 256
Tabla 11.1. Longitud de cadena para nombres de archivos en distintos sistemas operativos.
crear arreglo T N T
(n) x, donde x Tn T
T* crear_arreglo_T(int n){
return new T[n];
};
para el caso de las cadenas se crea un arreglo de datos de tipo char, es decir, para construir
cadenas se utiliza la funcion
es importante no olvidar que hay que tener en cuenta que si la cadena debe almacenar
a lo mas M smbolos, entonces el argumento de la funcion de la creacion de las cadenas
debe ser M + 1, con el fin de tener en cuenta el caracter de fin de cadena (NUL) que todas
las cadenas deben poseer.
190 CAPITULO 11. CADENAS DE CARACTERES
Para las cadenas se puede utilizar la misma funcion, pero se suele descartar la longitud
del arreglo directamente
En estas funciones es donde se encuentra la principal diferencia entre los arreglos usuales
de tipo caracter y las cadenas de caracteres aqu estudiadas. En el caso de las cadenas,
a los usuarios no se les pregunta por el tamano de la cadena, sino que se predefine un
tamano lo suficientemente grande como para almacenar la cadena mas larga con la que
sea necesario trabajar en la aplicacion desarrollada. Adicionalmente, tampoco se leeran
los caracteres uno por uno, sino que se leeran en conjunto, esto se hace mediante el uso de
la funcion getline de la librera iostream, esto es lo realmente interesante de las cadenas
con respecto a los arreglos de enteros o reales.
La lectura de cadenas se puede modelar mediante la siguiente funcion matematica
11.3. FUNCIONES GENERALES SOBRE CADENAS 191
En este caso el n debe ser pensado previamente, de tal manera que el tamano sea lo
suficientemente grande como para almacenar cualquier posible informacion que el usuario
desee guardar. Observese que no se empleo is >> x pues esta instruccion no podra leer
frases ya que por ejemplo, al leer la frase hola mundo quedara unicamente almacenada
la subcadena hola, por el contrario la funcion getline leera el flujo hasta encontrar
un salto de lnea o hasta que se alcance el tamano del arreglo que puede almacenarse en
la cadena creada inicialmente, en este ultimo caso se almacenara el prefijo de la cadena
que contenga los primeros n 1 smbolos y el smbolo n sera el caracter NUL (\0) de fin de
cadena .
Para imprimir una cadena en un flujo si se puede utilizar el operador << sobre flujos
Como se suele operar en cadenas con la informacion que sea proporcionada por un
usuario es necesario tener una funcion especial que nos indique cuantos caracteres hay
dentro de una cadena, esto es contar cuantos caracteres hay antes del caracter NUL, cuando
una cadena tiene longitud nula o igual a cero se dice que la cadena es una cadena vaca.
Ejemplo. Para la siguiente cadena se tiene que su longitud es igual a 5, no se tiene en
cuenta el fin de cadena, aunque el arreglo base tiene un tamano igual a 10.
h o l a \0 ?? ?? ?? ??
0 1 2 3 4 5 6 7 8 9
Una funcion que permite calcular la longitud de una cadena, que hace uso de una
funcion auxiliar recursiva es
Con la funcion de longitud se pueden definir funciones interesantes tales como copiar
cadena
11.3. FUNCIONES GENERALES SOBRE CADENAS 193
La librera cstdlib contiene dos funciones que son muy utiles y frecuentemente utili-
zadas, que permiten convertir informacion almacenada como cadenas a numeros enteros o
reales de acuerdo a su origen. Estas funciones son:
int atoi(char* <integer>): funcion que abrevia la frase alphabetic to integer (alfabeti-
co a entero) y que permite obtener un numero entero a partir de una cadena, en caso
de que la cadena del argumento <integer> no represente un entero entero valido,
entonces se retorna por defecto el valor 0.
double atof(char* <float>): funcion que abrevia la frase alphabetic to floating point
(alfabetico a punto flotante) y que permite obtener un numero real a partir de una
cadena, en caso de que la cadena del argumento <float> no represente un numero
real valido, entonces se retorna por defecto el valor 0.0.
En el siguiente ejemplo se crean dos cadenas de tamano maximo igual a 255, luego se
crea una cadena de tamano maximo igual a 2, a continuacion se solicita al usuario que
ingrese su nombre por teclado, este texto se copia a una nueva cadena, despues se solicita
al usuario que ingrese su edad como cadena, esta se convierte a entero mediante el uso
de la funcion atoi y luego se imprime en la consola tanto el nombre como su respectiva
edad, as que el codigo completo de cadenas quedara as.
194 CAPITULO 11. CADENAS DE CARACTERES
Ejemplo.
#include <iostream>
#include <cstdlib>
int main()
{
int n_nombre = 256;
// Crea una cadena de tamano 255
char* str = crear_cadena(n_nombre);
char* str_copia = crear_cadena(n_nombre);
int n_edad = 3;
// Crea una cadena de tamano 2
char* str_edad = crear_cadena(n_edad);
int edad;
system("pause");
return EXIT_SUCCESS;
};
11.3. FUNCIONES GENERALES SOBRE CADENAS 197
Ejercicios
Elabore un programa que dada una letra cuente cuantas ocurrencias de esta letra
hay.
Elabore un programa que dada una cadena diga si todos los smbolos de la cadena
son letras.
Elabore un programa que dada una cadena cuente las consonantes en dicha cadena.
Desarrollar un algoritmo que retorne un valor booleano que indique si dos cadenas
son iguales, esto es, que tienen la misma longitud con los mismos smbolos en la
mismas posiciones.
Desarrollar un algoritmo que invierta una cadena de caracteres (la cadena invertida
debe quedar guardada en una variable aparte).
ala es palindrome
anita lava la tina No es palindrome, pues al invertirla con espacios no es
exactamente igual a la original.
los estudiantes de programacion leyeron toda la gua no es palindrome.
robas ese sabor es palindrome
1 3 7 2 8
X = 9 11 5 6 4
6 2 1 1 1
x11 x1m
x12 x13 x1(m1)
x21 x2m
x22 x23 x2(m1)
X =
x(n1)1 x(n1)2 x(n1)3 x(n1)(m1) x(n1)m
x xnm
n1 xn2 xn3 xn(m1)
donde la matriz esta compuesta por n filas y m columnas, a esta matriz se le dice que es
de tamano n m.
columna j
x11 x1m
x1j
xi1 xim
xij
fila i
xn1 xnm
xnj
Cuando en una matriz se tiene que el numero de filas es igual al numero de columnas
se dice que la matriz es cuadrada.
X =
V F
F V
Una forma de entender la estructura interna de una matriz distinta a la definida pre-
viamente, es la de interpretarla como un arreglo de arreglos, esto es, verla como un arreglo
cuyas componentes son a su vez otros arreglos; como se explica a continuacion:
x11 x12 x1m x11 x12 x1m
= xi1 xi2 xim n
xi1 xi2 xim
n
x xnm x
n1 n2 n1 xn2 xnm
x
m
1
En el captulo 11.3.2 sobre arreglos, se definio un arreglo a partir del producto genera-
lizado de un conjunto T. El conjunto de los arreglos T se definio como la union de todos
los productos cartesianos del conjunto T, de la siguiente manera
T = Tm
mN
A partir del concepto de arreglo y usando la definicion i) de matrices por vectores fila se
puede ahora definir el conjunto de las matrices T como la union de todos los productos
cartesianos del conjunto de los arreglos del conjunto T, de la siguiente manera
n
T
= Tm
mN
nN
El producto externo debe entenderse como un producto cartesiano que genera vectores
columna y que internamente genera vectores fila, as como en la definicion i).
Un elemento generico del conjunto T es de la forma (Tm )n , donde n es el numero
de filas y m es el numero de columnas. Para abreviar, de aqu en adelante se utilizara la
notacion
(Tm )n Tnm .
Xij X[i-1][j-1]
en la posicion (n, m), similar a como se manejan las posiciones en notacion matematica
de matrices, es decir, para acceder en SciLab o MatLab a la variable almacenada en la
componente(i, j) se utiliza la equivalencia
Xij X[i][j]
Matematicamente se definira una rutina para la creacion de una matriz de tipo de datos
T como aquella rutina que dado un n N, que representa el numero de componentes del
arreglo columna, y m N que correspondiente al tamano del cada arreglo fila, retornara una
matriz de T de la siguiente manera
crear matriz T N N T
(n, m) X, donde X Tnm T
En C++ se traduce
m
1
n n
204 CAPITULO 12. MATRICES O ARREGLOS BIDIMENSIONALES
m m
2
n2
n n
m m
n1
n n n
Ejemplo. Para crear una matriz de tipo entero se tiene la siguiente funcion
Para eliminar una matriz, as como en el caso de los arreglos, se debe entender que lo
que ocurre es que la porcion del espacio de la memoria que se utiliza para almacenar los
arreglos fila de la matriz se regresan al sistema operativo para que este disponga de esa
memoria para almacenar nueva informacion.
Matematicamente se puede modelar esto como una funcion que dada la matriz X,
junto con el numero de filas n y el numero de columnas m (aunque este ultimo no se
requiere, pero se suele utilizar), se retorna la porcion del espacio de la memoria MX que
es utilizado para almacenar la matriz X, esto se hace liberando cada uno de los arreglos
fila que conforman la matriz, de esta manera la funcion se puede escribir as
12.3. LAS MATRICES EN COMPUTACION 205
Para traducir esta funcion a C++ se debe tener en cuenta que la funcion no retorna un
valor de un tipo de datos, si no que se regresa memoria al sistema operativo, por lo que la
funcion regresa un espacio que esta vaco y listo para utilizarse de nuevo.
El desbloqueo de la memoria y la liberacion del espacio utilizado por cada uno de los
arreglos fila Xi se escribe en C++ mediante la instruccion
delete[] X[i];
Luego de liberar cada uno de los arreglos fila se debe liberar el arreglo columna que los
contena, esto se escribe en C++ mediante la instruccion
delete[] X;
Al igual que en el caso de los arreglos, para decir que se retorna memoria vaca, en C++
esto se escribe como void y en el cuerpo de la funcion se utiliza la instruccion return;
para indicar que se retorno una porcion de espacio que esta vacio y que queda listo para
usarse de nuevo.
De esta manera, la traduccion de la funcion en C++ se escribe de la siguiente manera
n n n
n1
m m
206 CAPITULO 12. MATRICES O ARREGLOS BIDIMENSIONALES
n n
n2
2
m m
n n
1
m
Ejemplo. Para liberar la memoria usada por una matriz de tipo entero se tiene la siguiente
funcion
Dada una matriz de tipo T, es posible realizar operaciones de lectura y escritura sobre
flujos de datos, y dichas operaciones se realizan de la siguiente manera:
Lectura de matrices: para la entrada o lectura de una matriz desde un flujo de datos,
se puede utilizar la siguiente funcion
12.3. LAS MATRICES EN COMPUTACION 207
leer matriz T IS T N N T
(is, X, n, m) X, donde Xij = leer T(is),
i = 1, 2, 3, . . . , n,
j = 1, 2, 3, . . . , m
Ejemplo. En C++ para leer una matriz de tipo entero se utiliza la siguiente funcion
1 2
2
2 2
3 3
n = 2, m = 3, n = 2, m = 3,
5 5
21 13 8 21 13 8 i = 0, j = 0
3 4
2 3 2 3 5
3 5
5 8
n = 2, m = 3, n = 2, m = 3,
8 13
21 13 i = 0, j = 1 21 i = 0, j = 2
208 CAPITULO 12. MATRICES O ARREGLOS BIDIMENSIONALES
5 6
2 3 5 2 3 5
8 8
13 13 8
n = 2, m = 3, n = 2, m = 3,
21 21
i = 0, j = 3 i = 1, j = 0
7 8
2 3 5 2 3 5
13 21
21 8 13 8 13 21
n = 2, m = 3, n = 2, m = 3,
i = 1, j = 1 i = 1, j = 2
9 10
2 3 5 2 3 5
8 13 21 8 13 21
n = 2, m = 3, n = 2, m = 3,
i = 1, j = 3 i = 2, j = 3
Escritura de matrices: para enviar o escribir una matriz en un flujo de datos, se puede
definir la siguiente funcion
escribir matriz T OS T N N OS
(os, X, n, m) os, donde escribir T(Xij , os),
i = 1, 2, 3, . . . , n,
j = 1, 2, 3, . . . , m
En C++ se traduce as
12.3. LAS MATRICES EN COMPUTACION 209
Ejemplo. En C++ para escribir una matriz de tipo entero se utiliza la siguiente funcion
2
1
2 3 5 2 3 5
8 13 21 8 13 21
n = 2, m = 3, n = 2, m = 3, 2
i = 0, j = 0
3 4
2 3 5 2 3 5
8 13 21 8 13 21
n = 2, m = 3, 2 n = 2, m = 3, 3 2
i = 0, j = 0 i = 0, j = 1
210 CAPITULO 12. MATRICES O ARREGLOS BIDIMENSIONALES
5 6
2 3 5 2 3 5
8 13 21 8 13 21
2
n = 2, m = 3, 3 2 n = 2, m = 3, 5 3
i = 0, j = 1 i = 0, j = 2
7 8
2 3 5 2 3 5
8 13 21 2
8 13 21 2
3
n = 2, m = 3, 5 3 n = 2, m = 3, 8 5
i = 0, j = 3 i = 1, j = 0
9 10
2 3 5 2 3 5
8 13 21 2 3
8 13 21 2 3
5
n = 2, m = 3, 8 5 n = 2, m = 3, 13 8
i = 1, j = 0 i = 1, j = 1
11 12
2 3 5 2 3 5 2
2
8 13 21 3 5
8 13 21 3 5
8
n = 2, m = 3, 13 8 n = 2, m = 3, 21 13
i = 1, j = 1 i = 1, j = 2
13 14
2 3 5 2 2 3 5 2
3 3
8 13 21 5 8
8 13 21 5 8
n = 2, m = 3, 21 13 n = 2, m = 3, 21 13
i = 1, j = 3 i = 2, j = 3
12.3. LAS MATRICES EN COMPUTACION 211
15
2 3 5 2 3 5
8 13 21 8 13 21
Es posible utilizar lo visto en funciones para realizar diversidad de calculos que involu-
cren matrices.
Suponga que un archivo contiene unos datos numericos enteros tales que consta de 5
lneas de texto y en cada lnea hay dos numeros escritos que se encuentran separados por
una tabulacion as como se muestra a continuacion
0 1
2 3
4 5
6 7
8 9
Una funcion general que permite construir una nueva matriz que contiene el cuadrado
de cada componente de una matriz dada es
cuadrado matriz Z N N Z
(X, n, m) Y, donde Yij = Xij2 ,
i = 1, 2, . . . , n,
j = 1, 2, . . . , m
#include<iostream>
#include<cstdlib>
#include<fstream>
int main(){
int n = 5;
int m = 2;
ifstream ifs("matriz_numeros.txt");
ofstream ofs("matriz_cuadrados.txt");
int** X = crear_matriz_int(n, m);
X = leer_matriz_int(ifs, X, n, m);
int** Y = cuadrado_matriz(X, n, m);
escribir_matriz_int(ofs, Y, n, m);
liberar_matriz_int(X, n, m);
liberar_matriz_int(Y, n, m);
ifs.close();
ofs.close();
cout << "El calculo de la matriz fue exitoso" << endl;
system("pause");
return EXIT_SUCCESS;
};
tablas mult N N Z
(n, m) X, donde Xij = i j,
i = 1, 2, . . . , n,
j = 1, 2, . . . , m
En C++:
214 CAPITULO 12. MATRICES O ARREGLOS BIDIMENSIONALES
Ejemplo. Determinantes 2 2
Dado un sistema de ecuaciones de dos ecuaciones con dos incognitas
ax + by = c
a x + b y = c
=
a b x c
a b y c
ax0 + by0 = c y a x 0 + b y 0 = c .
det 2 2 R22 R
X X11 X22 X21 X12
En C++:
Una de los operaciones basicas sobre las matrices es el producto escalar. En este se elige
un valor sobre un campo (por ejemplo los reales R) y se multiplica este valor por cada
componente de la matriz.
12.3. LAS MATRICES EN COMPUTACION 215
x11 x12 x1m
x x2m
As, si R y X = 21
x22
xn1 xn2 xnm
entonces
x11 x12 x1m x11 x12 x1m
x x2m x21 x22 x2m
Y = X = 21 =
x22
xn1 xn2
xnm xn1 xn2 xnm
La definicion de esta funcion sera formalmente
producto escalar R R N N R
(, X, n, m) Y, donde Yij = Xij ,
i = 1, 2, . . . , n,
j = 1, 2, . . . , m
En C++:
Ejercicios
1. Desarrollar un algoritmo que permita hallar el vector solucion de un sistema de dos
ecuaciones con dos incognitas, utilizando la regla de Cramer.
6. Desarrollar un programa que sume los elementos de una columna dada de una matriz.
7. Desarrollar un programa que sume los elementos de una fila dada de una matriz.
10. Desarrollar un algoritmo que permita multiplicar dos matrices de numeros reales.
11. Desarrollar un algoritmo que determine si una matriz es magica. Se dice que una
matriz cuadrada es magica si la suma de cada una de sus filas, de cada una de sus
columnas y de cada diagonal es igual. Ejemplo:
8 1 6
3 5 7
4 9 2
12. Desarrollar un algoritmo que dado un entero, reemplace en una matriz todos los
numeros mayores al numero dado por un uno y todos los menores o iguales por un
cero.
Si el numero dado es: 5 y una matriz en el arreglo es:
8 1 6
3 5 7
4 9 2
1 0 1
La matriz de salida es:
0 0 1
0 1 0
12.3. LAS MATRICES EN COMPUTACION 217
13. Desarrollar un programa que genere una matriz marco cuadrada de tamano n n.
Entrada: n = 3
1 1 1
1 0 1
1 1 1
14. Desarrollar un programa que tome un arreglo de tamano n2 y llene en espiral hacia
adentro una matriz cuadrada de tamano n.
Ejemplo: arreglo de entrada: [1, 2, 3, 4, 5, 6, 7, 8, 9], la matriz de salida es:
1 2 3
8 9 4
7 6 5
16. Desarrollar un algoritmo que permita hallar la matriz inversa de una matriz cuadra-
da, si esta existe.
17. Desarrollar un algoritmo que permita calcular el determinante de una matriz cua-
drada, usando el teorema de Laplace (desarrollo por menores y cofactores).
218 CAPITULO 12. MATRICES O ARREGLOS BIDIMENSIONALES
Bibliografa
Bohm, C. & Jacopini, G. [1966]. Flow Diagrams, Turing Machines and Languages with
only Two Formation Rules, Comm. of the ACM 9(5): 366371.
Deitel, H. M. & Deitel, P. J. [2004]. Como programar en C, C++ y Java, Pearson Educa-
cion.
Kolman, B., Busby, R. C. & Ross, S. [1997]. Estructuras de matematicas discretas para la
computacion, Pearson educacion, Prentice-Hall Hispanoamericana.
Savitch, W. A. [2000]. Resolucion de problemas Con C++, 2nd edn, Pearson Educacion,
Mexico.
219