Sie sind auf Seite 1von 7

6 INSTRUCCIONES DE REPETICIN O CICLOS

Este captulo es parte de un libro an preparacin. Por esta razn los autores no se hacen
responsables de los errores y gazapos que en l puedan encontrarse. Por cortesa han sido
puestos a disposicin de los estudiantes de la carrera de Ciencia de la Computacin. Queda
prohibida la comercializacin, utilizacin en otros textos y transferencia a terceros sin el
consentimiento expreso de los autores. Los autores agradecen cualquier sugerencia o error que les
sea comunicado.
Las instrucciones condicionales que se estudian en el Captulo 5 permiten controlar el flujo
de ejecucin en un programa porque segn una condicin la ejecucin de las acciones puede tomar
un camino u otro.
En este captulo el lector encontrar otro grupo de instrucciones de control de flujo, pero esta
vez relacionadas con la repeticin de las acciones. Precisamente la solucin por computacin a
muchos problemas requiere de repetir una secuencia de acciones para lograr un objetivo, con ello
se aprovechan las cualidades en que las computadoras aventajan a los humanos: velocidad,
confiabilidad y "obediencia".
En este captulo se estudian las instrucciones de repeticin, tambin conocidas por ciclos. Una
instruccin de ciclo indicar la ejecucin repetidamente de un grupo de acciones mientras se
cumpla una condicin determinada, o para repetir el grupo de acciones una cantidad de veces, o
para aplicar las acciones a cada uno de los elementos de una coleccin. Para cada una de estas
diferentes causas y formas de repeticin existen instrucciones de ciclos apropiadas en C# que se
estudian en los epgrafes a continuacin.
6.1 Repeticin Condicional. Ciclo DO-WHILE.
En el Captulo 2 se estudia un ejemplo de programa para medir el tiempo que Ud. puede
demorar en teclear su nombre:
class ElTercerPrograma {
static void Main() {
Console.WriteLine("Por favor, teclee su nombre y pulse Enter");
Cronometro c = new Cronometro();
c.Arranca();
string s = Console.ReadLine();
c.Para();
Console.WriteLine("Te has demorado " + c.Tiempo + "milisegundos");
}
}
Claro este programa no puede controlar si el nombre tecleado es el verdadero, es decir si Ud.
no ha cometido ningn error al teclear su nombre
2
. Para tratar de asegurarse que el nombre
tecleado es el correcto se le pedir que lo teclee nuevamente, si la segunda vez lo teclea igual que

2
Se considera que el lector no tiene ningn inters en engaar al programa tecleando concientemente un nombre que
no es el suyo.

Miguel Katrib y Grupo WEBOO-UH

2
la primera se considerar que el nombre tecleado es el correcto
1
. Pero si no son iguales entonces
se quiere repetir el intento de volver a teclear dos veces el nombre y medir el tiempo hasta que lo
haga correctamente.
Para resolver este problema es necesario poder escribir una instruccin que indique repetir el
proceso de teclear el nombre mientras no lo teclee igual dos veces seguidas. Esto se muestra en el
cdigo a continuacin:
1 class ElTercerProgramaMejorado {
2 static void Main() {
3 Cronometro c = new Cronometro();
4 do {
5 Console.WriteLine(Por favor, teclee su nombre );
6 string nombre1 = Console.ReadLine();
7 Console.WriteLine(Por favor, vulvalo a teclear );
8 c.Arranca();
9 string nombre2 = Console.ReadLine();
10 c.Para();
11 } while (nombre != nombre2);
12 Console.WriteLine("Ha demorado " + c.Tiempo +
13 " milisegundos en teclear su nombre");
14 }
15}
En la lnea 4 con la palabra reservada do se indica el comienzo de la secuencia de
instrucciones a ejecuta repetidamente que van de la lnea de la 5 a la 10. Note que se indica dos
veces teclear el nombre el cual se guarda en las variables nombre1 y nombre2 de tipo string. La
lnea 11 tiene la condicin de repeticin del ciclo, que es en este caso while (nombre !=
nombre2); esto se lee como mientras nombre1 sea distinto de nombre2 repetir el ciclo. Es decir, si
la expresin (nombre1 != nombre2) evala true entonces se vuelve a repetir la ejecucin de las
acciones agrupadas entre el do y el while.
La sintaxis de esta instruccin de ciclo conocida como do-while es:
do
<instruccin>
while (<condicin>)
Esta instruccin do-while ejecuta la <instruccin> (que puede ser una secuencia de
instrucciones si se agrupan entre las llaves { y }). Luego se evala <condicin> y si la evaluacin
es true se vuelve a repetir la <instruccin>, si es false se contina en la instruccin que siga al
while.
6.2 Repeticin Condicional. Ciclo WHILE.
C# tiene otra variante de ciclo de repeticin por condicin. En el ciclo do-while anterior , es
necesario ejecutar al menos una vez la secuencia de instrucciones del ciclo y luego se pregunta por
la condicin para decidir si ste se vuelve a repetir. Este tipo de ciclos se puede resumir en la frase
"hacer mientras se cumpla la condicin". Esto es aplicable al ejemplo anterior porque hay que
teclear los nombres al menos una vez antes de decidir si se repite porque no coinciden. Pero

1
Ciertamente esto supone que Ud. no va a equivocarse dos veces seguidas de la misma manera ?.
4
En lo que se considera como ejemplo del "primer algoritmo registrado por la historia", por supuesto que muchsimo
antes de que se pensara en computadoras.
CAP 6 INSTRUCCIONES DE REPETICION O CICLOS
Miguel Katrib y Grupo WEBOO-UH
3
tambin hay situaciones en que se quieren ciclos bajo la interpretacin "mientras se cumpla la
condicin, hacer. Este es el caso de la instruccin conocida solamente como ciclo while:
while (<condicin>)
<instruccin>
En este ciclo se evala primero <condicin> y si esta es true entonces se ejecuta
<instruccin> (que recuerde puede ser una secuencia de instrucciones entre llaves { y }).
Despus que se ejecute <instruccin> se vuelve a preguntar por la condicin para decidir si el ciclo
se repite de nuevo. El siguiente ejemplo ilustra el uso de la instruccin while.
Considere el problema de hallar el mximo comn divisor (MCD) entre dos nmeros enteros
positivos. El MCD es el mayor nmero natural que divide simultneamente a ambos nmeros. Por
ejemplo, el MCD entre 12 y 8 es 4, ya que cualquier otro nmero natural mayor que 4, no lo divide
a los dos (por ejemplo, el 6 divide a 12 pero no a 8, y el 8 divide al 8, pero no al 12). Luego este
problema radica en encontrar el mayor nmero que divida a ambos enteros. Por otra parte, es
evidente que el MCD entre m y n no puede ser un nmero mayor que ninguno de los dos Esto se
puede expresar con un ciclo que empiece con el menor de m y n y vaya probando con todos los
menores que l hasta encontrar a un nmero que los divida ambos. Note en el cdigo a
continuacin como se calcula el mnimo de dos nmeros utilizando el mtodo System.Math.Min
(lnea 5) y se comienza la variable result con ese valor. La condicin de repeticin (m % result
!= 0 || n % result != 0) evaluar true y por tanto ejecutar las instrucciones del ciclo (lnea
7 solamente en este ejemplo) si el nmero divide a alguno de los dos m o n. La condicin evaluar
false cuando se encuentre un nmero result que los divida a ambos (note que hay garanta de
que esto ocurrir ya que al menos el 1 siempre divide a cualquier nmero), en ese caso el ciclo se
dejar de repetir y ese valor de result es el que se retorna como resultado del mtodo (lnea 8).
1 static int Mcd(int m, int n) {
2 if (m<=0 || n<=0)
3 throw new System.Exception("Nmeros deben ser positivos");
4 else
5 int result = Math.Min(m, n);
6 while (m % result != 0 || n % result != 0)
7 result--;
8 return result;
9 }

Intente seguir la ejecucin de este mtodo para los valores 60 y 12, que debe dar como
resultado 6.
Este mismo problema se puede resolver de una manera ms eficiente. El algoritmo a
continuacin fue propuesto por Eucldes
4
. Este algoritmo se basa en la propiedad siguiente.
Sean m y n dos nmeros naturales y sea r el resto de la divisin de m por n (r=m%n en C#). Si
r es cero (r == 0), significa que m es divisible por n, y como n es asimismo divisible por n,
entonces el MCD entre m y n es n. Ahora, si r no es cero, el problema de hallar el MCD entre m y n,
es equivalente a hallar el MCD entre n y r. La segunda variante, cuando r != 0, aparenta ser
paradjica, puesto que resulta en tener que encontrar el MCD de otros dos nmeros, que es el
mismo problema inicial. Pero resulta que es posible demostrar (ver Captulo 9 sobre Recursividad)
que si a n y r se le aplica el mismo esquema que a m y n de manera sucesiva, se llega al caso en

Miguel Katrib y Grupo WEBOO-UH

4
que el resto de la divisin es cero. Y se llega haciendo menos repeticiones que las que hace la
implementacin anterior.
1 static int Mcd(int m, int n) {
2 if (m<=0 || n<=0)
3 throw new System.Exception("Nmeros deben ser positivos");
4 int r = m % n;
5 while (r !=0) {
6 m = n;
7 n = r;
8 r = m % n;
9 }
10 return n;
11}

Pruebe a ejecutar el cdigo anterior con los mismos valores 60 y 12 de la primera
implementacin verifique cuntas repeticiones se hacen en este caso.
ara que el lector pueda comparar la eficiencia de ambas implementaciones, determine cuantas
repeticiones deben ocurrir en cada una para los nmeros 55 y 34.
6.3 Repeticiones por cantidad. Ciclos FOR.
Gauss, fue uno de los matemticos ms grandes de inicios del siglo XI X. Se cuenta que
cuando Gauss asista a sus primeros aos en la escuela, mostraba muy poco inters por las
matemticas que le impartan. En una ocasin en que el nio hiciera una travesura en sus clases de
matemticas, su profesor, sabiendo que el nio mostraba poco inters por el tema, le puso como
castigo resolver un problema: sumar todos los nmeros del uno al cien, deba dar el resultado al
profesor para poder irse a casa. El profesor qued muy sorprendido cuando a los pocos minutos el
nio le entregara la respuesta de 5500.
Si Gauss hubiera podido disponer de una computadora con C# podra haber resuelto el
problema programando el ciclo siguiente:
1 publis static int SumaCienPrimeros(){
2 int result = 0;
3 int k = 1;
4 while (k<=100){
5 result+=k;
6 k++;
7 }
8 return result;
9 }

Note como el cdigo anterior empieza con valor de k igual a 1 (lnea 3) y luego repite el ciclo
mientras k sea menor o igual que 100 (lnea 4). En cada repeticin del ciclo va sumando el valor
de k con lo que tiene acumulado en la variable result (que fue adecuadamente inicializada en 0
en la lnea 2). Note tambin como en cada repeticin del ciclo se incrementa el valor de k (lnea 6)
de este modo se irn recorriendo todos los nmeros hasta el 100. Cuando k tome el valor 101 la
CAP 6 INSTRUCCIONES DE REPETICION O CICLOS
Miguel Katrib y Grupo WEBOO-UH
5
condicin (k<=100) evaluar false y el ciclo se dejar de repetir pasando a la lnea 8 donde se
retorna el resultado.
El ejemplo anterior muestra un patrn comn en muchos ciclos. Se utiliza una variable (k en
el ejemplo) que se suele llamar variable de control. A este variable se le da un valor inicial (el k=1;
de la lnea 3 en el caso de este ejemplo). Luego el ciclo depende de una condicin (el k<=100 en
la lnea 4) en la que est involucrada dicha variable (de ah el nombre de variable de control).
Dentro del ciclo la variable de control cambia de valor (el k++ de la lnea 6) de modo tal que en
algn momento se deje de cumplir la condicin de repeticin y el ciclo termina.
Para los casos en que un ciclo presente variables de control, existe en C# una instruccin de la
familia de los ciclos que distingue claramente las variables de control y su actualizacin. La
instruccin tiene la siguiente sintaxis.
for (<inicializacin>; <condicin>; <actualizacin>)
<instruccin>
La solucin, del problema de Gauss utilizando el ciclo for es la siguiente.
public static int SumaCien2 {
int resultado = 0;
for (int cantidad = 0; cantidad < 100; cantidad++)
resultado += cantidad + 1;
return resultado;
}
Observe que en con el ciclo for se declara la variable de control, se inicializa y se actualiza
dentro de la misma definicin de la instruccin.
De todas maneras Gauss !no dispona de computadoras! Cmo pudo entonces el pequeo
Gauss resolver este problema tan rpidamente? Para ello, se vali de un razonamiento que
revelaba el genio que comenzaba a manifestarse en l.
6.3.1 Nmeros Primos
En una de las ramas ms antiguas e interesantes de las matemticas, la teora de nmeros,
uno de los conceptos ms importantes es el de nmero primo. Se dice que un nmero entero y
positivo es primo si es divisible de manera exacta solamente por 1 y por l mismo. Por ejemplo, el
2, el 3, el 5 y el 7 son nmeros primos, ya que son divisibles por 1 y por ellos mismos, pero no lo
son por ningn otro entero diferente. Por otro lado, el 4 no es primo, por ser divisible por 2, ni el 6
que es divisible por 2 y por 3. De esta definicin se han derivado cientos de propiedades de los
nmeros y se ha aplicado no slo en el rea de las matemticas.
El problema fundamental relacionado con los nmeros primos es el de determinar si un
nmero entero n dado, es un nmero primo o no. Para ello basta con comprobar que el nmero no
es divisible por ninguno de los nmeros del 2 al n-1. La implementacin de esta primera idea de
solucin es la siguiente.
public static bool EsPrimo1(int n)
{
for (int i = 2; i < n; i++)
if (n % i == 0)
return false;
return true;
}
Observe cmo la implementacin consiste de un ciclo donde se verifica para todos los
nmeros del 2 al n-1 (los valores que va tomando la variable de control i) si se cumple la

Miguel Katrib y Grupo WEBOO-UH

6
condicin n % i == 0. Si se cumple esta condicin, significa que el nmero n es divisible por i,
que est entre 2 y n-1, luego, el nmero no es primo y se retorna false. Si el nmero es primo, la
condicin n % i == 0 es falsa para todos los valores que toma i en el ciclo, por lo que se termina
el ciclo y se retorna true con la ltima instruccin.
Por la definicin de la instruccin for, es posible asumir que la nica manera de que un ciclo
deje de repetir las instrucciones anidadas, es que deje de cumplirse la condicin del ciclo. En el
ejemplo la condicin es i < n, lo que indica que el ciclo se har hasta que la variable i tome el
valor de n-1, ya que en la prxima repeticin se actualiza con i++ y deja de cumplirse i < n. Sin
embargo, en el mismo ejemplo se muestra otra manera de salir del ciclo, que es a travs de la
instruccin return. Esta instruccin se defini en los captulos previos como una instruccin que
provoca la terminacin de la ejecucin de un mtodo, y en este caso no hace menos. Si en la
ejecucin de un mtodo se alcanza una instruccin return, se termina la ejecucin del mtodo,
an si la ejecucin se encontraba dentro de un ciclo, como en este caso.
Ms adelante, en este captulo el lector conocer otras instrucciones especiales que le servirn
para controlar la ejecucin de los ciclos, y abortar o modificar cmo se comportan las instrucciones
cclicas.
Retomando el ejemplo de los nmeros primos, es posible determinar si n es primo sin
necesidad de hacer la verificacin con cada uno de los nmeros del 2 al n-1.
En primer lugar, no es necesario que la variable i tome valores mayores que la mitad de n.
Esto se debe a que ningn nmero mayor que la mitad de n puede ser un divisor de n, o sea, el
mayor divisor de n no puede ser mayor que su mitad. Si suponemos que pueda existir un divisor de
n mayor que su mitad y menor que l mismo, se llega a la contradiccin de que tiene que existir
otro divisor entero de n que est entre 1 y 2, excluyendo a estos, lo que es imposible. De esta
manera el ciclo no tiene que asignar n-2 valores diferentes a la variable i, sino la mitad de esto, o
sea n/21. Con esta mejora se obtiene la siguiente implementacin.
public static bool EsPrimo2(int n)
{
for (int i = 2; 2*i <= n; i++)
if (n % i == 0)
return false;
return true;
}
Por ejemplo, si n=5, la variable i toma solamente el valor i=2, ya que cuando se actualiza con
i++, para i=3 no se cumple 2*i <= n, o sea, 6 <= 5. Slo se analiza i=2, en lugar de analizar
todos los valores 2, 3 y 4
1
, y resulta en decir que el cinco es primo. Por otra parte, observe el caso
cuando n=3. Si esto ocurre, se inicializa la variable de control i=2, luego se verifica la condicin del
ciclo 2*i<=n, que evala a false puesto que 2*2<=3 es falso. Entonces no se ejecutan las
instrucciones del ciclo ni tan slo la primera vez, y se contina con la instruccin return true.
Realmente se puede ser ms osado, y hacer que la variable de control i tome los valores
desde el 2 hasta la raz cuadrada del nmero, en lugar de hasta la mitad de este.

1
El lector debe realizar una demostracin ms formal de que esta optimizacin funciona si desea convencerse o
practicar.
CAP 6 INSTRUCCIONES DE REPETICION O CICLOS
Miguel Katrib y Grupo WEBOO-UH
7
6.4 Ejercicios
1. Compare la ejecucin de las dos implementaciones propuestas en el epgrafe 6.2 para calcular
el Mcd al ejecutarlas con el par de nmeros 60 y 12 y con el par de nmeros 55 y 34.
2. Reelabore la implementacin del algoritmo de Eucldes para calcular el mximo comn divisor
si no se dispusiera de la operacin de mdulo % ni de la operacin de divisin /.
3.

Das könnte Ihnen auch gefallen