El algoritmo de Euclides sirve para obtener el mximo comn
divisor (abreviado normalmente como M.C.D.) de dos nmeros enteros
positivos. El mnimo comn mltiplo (M.C.M.), puede obtenerse tambin con ste algoritmo, haciendo una sencilla operacin con el M.C.D. obtenido. En este artculo hablamos de cmo programarlo. Puedes encontrar una demostracin en lnea al final de sta pgina. Se llama as por Euclides de Alejandra, un matemtico griego que vivi en los tiempos del faran Ptolomeo I, del que nos han quedado algunos textos recopilatorios del saber matemtico y geomtrico de su poca. No es que Euclides escribiera tal cual ste algoritmo, sino que, aparentemente, dej escritas algunas relaciones entre nmeros que son la base de lo que hoy llamamos MCD. Es uno de los algoritmos tpicos que los profesores de programacin ponen a sus alumnos para practicar el bucle repetir-mientras o hacer-hasta (repeatuntil o do-while) pasando valores de una iteracin a otra del bucle.
Mximo Comn Divisor (MCD)
El mximo comn divisor de dos nmeros enteros positivos a y b es otro nmero entero positivo c tal que si dividimos a/c y b/c, los restos de las divisiones son 0, y adems no existe otro nmero mayor que c que tenga esta caractersitica. Como nos decan en el "cole", elmximo comn dvisor (mcd) de dos enteros a y b es el mayor entero c que divide exactamente aayb. Aunque en el colegio nos ensean a encontrar el mcd a partir de lade a y b, esa no es una buena forma de obtener el mcd computacionalmente, ya que el algoritmo para descomponer en factores primos es muy costoso, en trminos de computacin. El algoritmo de Euclides es bastante ms eficiente para obtener el mcd, aunque normalmente sorprende un poco cuando tenemos contacto con l por primera vez.
El algoritmo de Euclides es el siguiente:
Siendo a y b dos enteros positivos tales que a>b, comenzamos
dividiendo a/b, con lo que obtendremos un resto r1 y un cociente q1. Hacemos la operacin q1=a/b, utilizando la divisin entera, sin decimales.... pero realmente no slo nos interesa el resultado o cociente de la divisin, sino que nos interesa tambin el resto, as que la operacin la vamos a reescribir de otra forma. Es importante que llamemos "a" al mayor de los dos nmeros (siempre el mayor va a ser a). Debemos dividir a entre b y obtener un cociente (al que llamaremos q1) y un resto (al que llamaremos r1). Obtenidos ese cociente y ese resto, se cumple que: a=q1b+r1 Los lenguajes de programacin suelen tener un operador para efectuar la divisin entera (con lo que obtendremos q1. Por ejemplo, en C#: q1=a/b;), y otro para obtener el resto o mdulo de la divisin (con lo que obtendremos r1. Por ejemplo, en C#: r1=a%b;1). A partir de esa primera divisin, es necesario repetir un proceso:
dividir el numero que fue divisor en el paso anterior entre el resto
obtenido en el paso anterior
despreciar el cociente
si el resto obtenido esta vez es 0, el mcd es el divisor de esta operacion,
es decir, el ltimo resto no nulo (recordemos que el divisor de esta operacin fu el resto en la anterior.
Si el resto no es 0, ir al primer paso
Es un poco engorroso la primera vez, pero realmente es un algoritmo muy
sencillo. Siguiendo con el ejemplo, en la segunda iteracin, dividiramos b/r1 obteniendo un resto r2(hacemos la operacin de divisin para obtener el
cociente, al que llamamos q2 y la de obtener el resto, al que llamamos r2), de
tal manera que se cumplira lo siguiente: b=q2r1+r2 En la tercera iteracin, dividimos r1/r2 obteniendo un resto r3 r1=q3r2+r3 Y se contina as hasta obtener un resto 0. El ltimo resto (llammosle r k) distinto de cero es el mcd. rk-2=qkrk-1+rk rk-1=qk+1rk+0 rk es el mcd(a,b) Es decir, empezamos dividiendo un nmero entre otro (obteniendo el resto tambin, no slo el cociente), y a partir de ah, seguimos dividiendo el nmero ms pequeo entre el resto que nos ha salido... y continuamos dividiendo por el resto anterior una vez y otra hasta que en ese proceso repetitivo obtengamos un resto que sea 0. Ya lo tenemos!. El mcd es es resto anterior (que no es cero). Como comentbamos al principio, es muy sencillo implementarlo iterativamente. Basta tener en cuenta que en cada vuelta del bucle, y siempre a partir de la segunda iteracin hay que hacer que el divisor sea el resto de la iteracin anterior y el dividendo sea el divisor de la iteracin anterior. Vamos a hablar de cdigo utilizando C#.
En el cdigo que construiremos vamos a utilizar dos variables enteras i1 e i2,
que inicialmente van a contener los valores de los dos enteros a y b que se pasen como parmetros, de tal manera que i1 tendr al mayor de los dos, e i2 al ms pequeo... y a partir de ah nos metemos en un bucle. La dinmica es siempre la misma: obtenemos el resto de la divisin, y si no es 0, debemos hacer otra repeticin. Pero antes de la siguiente repeticin, desplazamos los valores: lo que contena i1 ya no nos sirve. Metemos en i1 lo que tiene i2, y en i2 el resto que hemos obtenido.... //en C# static int EuclidesMCD(int a, int b) {
int iaux; //auxiliar
a = Math.Abs(a); //tomamos valor absoluto b = Math.Abs(b); int i1=Math.Max(a,b); //i1 = el ms grande int i2=Math.Min(a,b); //i2 = el ms pequeo do { iaux = i2; //guardar divisor i2 = i1 % i2; //resto pasa a divisor i1 = iaux; //divisor pasa a dividendo } while (i2 != 0); return i1; //ultimo resto no nulo
Al principio cuesta un poco de coger... te recomiendo hacer una traza
mentalmente (o mejor, ayudndote de papel). Te dars cuenta de cmo se van "desplazando los valores" a medida que vamos dividiendo hasta obtener el resto 0... aunque, realmente... no estamos utilizando los cocientes, sino slo los restos ;-) Aunque en la introduccin hemos mencionado la divisin ("/"), realmente no es del todo cierto... slo queremos los restos, no el cociente...(operador mdulo o resto: "%" en C#). Hemos introducido esta pequea "trampa" en la explicacin (pero no en el cdigo) porque cuando dividimos "a mano", realmente en la misma operacin de divisin obtenemos dos resultados a la vez: por un lado el cociente y por otro, el resto. Sin embargo, los lenguajes de programacin hacen cada una de esas cosas por separado: pueden obtener un cociente sin necesidad de obtener un resto y al revs, obtener un resto sin necesidad de dividir... as que en nuestro algoritmo no dividimos realmente: slo obtenemos el resto. Si lo hiciramos "a mano", tendramos que dividir, con lo que obtendramos el cociente y el resto simultneamente, pero despreciaramos el cociente y nos quedaramos slo con el resto.
Mnimo Comn Mltiplo. (MCM)
Muy relacionado con el mximo comn divisor est el mnimo comn mltiplo (mcm).
El mcm de dos enteros positivos a y b es un valor c entero y positivo tal que
al dividir c/a y c/b el resto es 0, y adems no existe otro nmero menor que c que cumpla esta condicin. Hay una relacin muy sencilla entre mcm y mcd. Es sta: mcm(a,b)=(ab)/mcd(a,b) As pues, tambin podemos obtener el mcm mediante el algoritmo de Euclides. static int EuclidesMCM(int a, int b) { return (a / EuclidesMCD(a, b)) * b; }
Observa que primero se divide a entre el mcd, en lugar de multiplicar ab.
Esto se hace para evitar un posible desbordamiento al multiplicar ab.