El algoritmo binario del mcd
El máximo común divisor (mcd) de dos números enteros no negativos se puede calcular mediante un algoritmo binario basado en las siguientes propiedades:
- Si a,b son pares, entonces mcd(a,b) = 2*mcd(a/2,b/2)
- Si a es par y b impar, entonces mcd(a,b) = mcd(a/2,b)
- Si a es impar y b par, entonces mcd(a,b) = mcd(a,b/2)
- Si a y b son impares y a > b, entonces mcd(a,b) = mcd((a-b)/2,b)
- Si a y b son impares y a < b, entonces mcd(a,b) = mcd(a,(b-a)/2)
- mcd(a,0) = a
- mcd(0,b) = b
- mcd(a,a) = a
Por ejemplo, el cálculo del mcd(660,420) es
1 2 3 4 5 6 7 8 9 |
mcd(660,420) = 2*mcd(330,210) [por 1] = 2*2*mcd(165,105) [por 1] = 2*2*mcd(30,105) [por 4] = 2*2*mcd(15,105) [por 2] = 2*2*mcd(15,45) [por 4] = 2*2*mcd(15,15) [por 4] = 2*2*15 [por 8] = 60 |
Definir la función
1 |
mcd :: Integer -> Integer -> Integer |
Definir la función
tal que (mcd a b) es el máximo común divisor de a y b calculado mediante el algoritmo binario del mcd. Por ejemplo,
1 2 3 |
mcd 660 420 == 60 mcd 3 0 == 3 mcd 0 3 == 3 |
Comprobar con QuickCheck que, para los enteros no negativos, las funciones mcd y gcd son equivalentes.
Soluciones
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import Test.QuickCheck mcd :: Integer -> Integer -> Integer mcd a 0 = a mcd 0 b = b mcd a b | a == b = a | even a && even b = 2 * mcd (a `div` 2) (b `div` 2) | even a = mcd (a `div` 2) b | even b = mcd a (b `div` 2) | a > b = mcd ((a-b) `div` 2) b | otherwise = mcd a ((b-a) `div` 2) -- Propiedad de equivalencia prop_mcd :: Integer -> Integer -> Bool prop_mcd a b = mcd a1 b1 == gcd a1 b1 where a1 = abs a b1 = abs b -- La comprobación es -- λ> quickCheck prop_mcd -- +++ OK, passed 100 tests. |
4 Comentarios