{"id":1439,"date":"2015-05-11T06:00:02","date_gmt":"2015-05-11T04:00:02","guid":{"rendered":"http:\/\/www.glc.us.es\/~jalonso\/exercitium\/?p=1439"},"modified":"2021-04-25T17:12:21","modified_gmt":"2021-04-25T15:12:21","slug":"representacion-decimal-de-numeros-racionales-1","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/representacion-decimal-de-numeros-racionales-1\/","title":{"rendered":"Representaci\u00f3n decimal de n\u00fameros racionales"},"content":{"rendered":"<p>Continuando con los ejercicios propuestos por los alumnos, Antonio Garc\u00eda Bl\u00e1zquez ha propuesto un ejercicio que usa el per\u00edodo de los n\u00fameros decimales. El ejercicio de hoy, basado en su propuesta, trata de la representaci\u00f3n decimal de los n\u00fameros racionales.<\/p>\n<p>Los n\u00fameros decimales se representan por ternas, donde el primer elemento es la parte entera, el segundo es el anteper\u00edodo y el tercero es el per\u00edodo. Por ejemplo,<\/p>\n<pre lang=\"text\">\n    6\/2  = 3                  se representa por (3,[],[])\n    1\/2  = 0.5                se representa por (0,[5],[])\n    1\/3  = 0.333333...        se representa por (0,[],[3])  \n   23\/14 = 1.6428571428571... se representa por (1,[6],[4,2,8,5,7,1])\n<\/pre>\n<p>Su tipo es<\/p>\n<pre lang=\"text\">\n   type Decimal = (Integer,[Integer],[Integer])\n<\/pre>\n<p>Los n\u00fameros racionales se representan por un par de enteros, donde el  primer elemento es el numerador y el segundo el denominador. Por ejemplo, el n\u00famero 2\/3 se representa por (2,3). Su tipo es<\/p>\n<pre lang=\"text\">\n   type Racional = (Integer,Integer)\n<\/pre>\n<p>Definir las funciones<\/p>\n<pre lang=\"text\">\n   decimal  :: Racional -> Decimal\n   racional :: Decimal -> Racional\n<\/pre>\n<p>tales que<\/p>\n<ul>\n<li>(decimal r) es la representaci\u00f3n decimal del n\u00famero racional r. Por ejemplo, <\/li>\n<\/ul>\n<pre lang=\"text\">\n        decimal (1,4)    ==  (0,[2,5],[])\n        decimal (1,3)    ==  (0,[],[3])\n        decimal (23,14)  ==  (1,[6],[4,2,8,5,7,1])\n<\/pre>\n<ul>\n<li>(racional d) es el n\u00famero racional cuya representaci\u00f3n decimal es d. Por ejemplo,<\/li>\n<\/ul>\n<pre lang=\"text\">\n        racional (0,[2,5],[])           ==  (1,4)\n        racional (0,[],[3])             ==  (1,3)\n        racional (1,[6],[4,2,8,5,7,1])  ==  (23,14)\n<\/pre>\n<p>Con la funci\u00f3n decimal se puede calcular los per\u00edodos de los n\u00fameros racionales. Por ejemplo,<\/p>\n<pre lang=\"text\">\n   ghci> let (_,_,p) = decimal (23,14) in concatMap show p\n   \"428571\"\n   ghci> let (_,_,p) = decimal (1,47) in concatMap show p\n   \"0212765957446808510638297872340425531914893617\"\n   ghci> let (_,_,p) = decimal (1,541) in length (concatMap show p)\n   540\n<\/pre>\n<p>Comprobar con QuickCheck si las funciones decimal y racional son inversas.<\/p>\n<h4>Soluciones<\/h4>\n<pre lang=\"haskell\">\n-- ---------------------------------------------------------------------\n-- \u00a7 Librer\u00edas auxiliares                                             --\n-- ---------------------------------------------------------------------\n\nimport Data.List\nimport Test.QuickCheck\n\n-- ---------------------------------------------------------------------\n-- \u00a7 Tipos                                                            --\n-- ---------------------------------------------------------------------\n\n-- Un n\u00famero racional se representa por un par de enteros, donde el\n-- primer elemento es el numerador y el segundo el denominador.\ntype Racional = (Integer,Integer)\n\n-- Un n\u00famero decimal es una terna donde el primer elemento es la parte\n-- entera, el segundo es el anteper\u00edodo y el tercero es el per\u00edodo.\ntype Decimal = (Integer,[Integer],[Integer])\n\n-- ---------------------------------------------------------------------\n-- \u00a7 De racional a decimal                                            --\n-- ---------------------------------------------------------------------\n\n-- (mayorExponente a x) es el mayor n tal que a^n divide a x. Por ejemplo,\n--    mayorExponente 2 40  ==  3\n--    mayorExponente 5 40  ==  1\n--    mayorExponente 5 41  ==  0\nmayorExponente :: Integer -> Integer -> Integer\nmayorExponente a x = head [n | n <- [1..], mod x (a^n) \/= 0] - 1\n\n-- (longitudAnteperiodo n) es la longitud del anteper\u00edodo de 1\/n (y de\n-- cualquier fracci\u00f3n irreducible de denominador n). Por ejemplo, \n--    longitudAnteperiodo 2   ==  1\n--    longitudAnteperiodo 3   ==  0\n--    longitudAnteperiodo 14  ==  1\nlongitudAnteperiodo :: Integer -> Integer\nlongitudAnteperiodo n = max (mayorExponente 2 n) (mayorExponente 5 n)\n\n-- (longitudPeriodo n) es la longitud del per\u00edodo de 1\/n (y de\n-- cualquier fracci\u00f3n irreducible de denominador n). Por ejemplo, \n--    longitudPeriodo 2  ==  0\n--    longitudPeriodo 3  ==  1\n--    longitudPeriodo 7  ==  6\nlongitudPeriodo :: Integer -> Integer\nlongitudPeriodo n\n    | m == 1    = 0 \n    | otherwise = head [k | k <- [1..], (10^k) `mod` m == 1]\n    where m = n `div` (2^(mayorExponente 2 n) * 5^(mayorExponente 5 n))\n\n-- (expansionDec (x,y)) es la expansi\u00f3n decimal de x\/y. Por ejemplo, \n--    take 10 (expansionDec (1,4))    ==  [0,2,5]\n--    take 10 (expansionDec (1,7))    ==  [0,1,4,2,8,5,7,1,4,2]\n--    take 12 (expansionDec (90,7))   ==  [12,8,5,7,1,4,2,8,5,7,1,4]\n--    take 12 (expansionDec (23,14))  ==  [1,6,4,2,8,5,7,1,4,2,8,5]\nexpansionDec :: Racional -> [Integer]\nexpansionDec (x,y) \n    | r == 0    = [q] \n    | otherwise = q : expansionDec (r*10,y)\n    where (q,r) = quotRem x y\n\n-- (parteEntera (a,b)) es la parte entera de a\/b. Por ejemplo,\n--    parteEntera (125,3)  ==  41\nparteEntera :: Racional -> Integer\nparteEntera (a,b) = a `div` b\n\n-- (antePeriodo (a,b)) es el anteper\u00edodo de a\/b; es decir, la lista de\n-- cifras que se encuentran entre la parte entera y el primer per\u00edodo de\n-- a\/b. Por ejemplo,\n--    antePeriodo (23,14)  ==  [6]\n--    antePeriodo (1,5)    ==  [2]\nantePeriodo :: Racional -> [Integer]\nantePeriodo (a,b) = genericTake s (tail xs)\n    where xs = expansionDec (a,b)\n          s  = longitudAnteperiodo b\n\n-- (periodo (a,b)) es el per\u00edodo de a\/b. Por ejemplo, \n--    periodo (1,3)                   ==  [3]\n--    periodo (1,5)                   ==  []\n--    periodo (1,7)                   ==  [1,4,2,8,5,7]\n--    periodo (23,14)                 ==  [4,2,8,5,7,1]\n--    concatMap show $ periodo (1,29) == \"0344827586206896551724137931\"\nperiodo :: Racional -> [Integer]\nperiodo (a,b) = genericTake t (genericDrop (1+s) xs)\n    where xs = expansionDec (a,b)\n          s  = longitudAnteperiodo b\n          t  = longitudPeriodo b\n\n-- (reducido (a,b)) es la forma reducida del n\u00famero racional a\/b. Por\n-- ejemplo, \n--    reducido (40,80)  ==  (1,2)\nreducido :: Racional -> Racional\nreducido (a,b) = (a `div` m, b `div` m) \n    where m = gcd a b\n\n-- (decimal (x,y)) es la forma decimal de x\/y; es decir, la terna\n-- formada por la parte entera, la parte decimal pura y la parte decimal\n-- peri\u00f3dica. Por ejemplo, \n--    decimal (1,4)    ==  (0,[2,5],[])\n--    decimal (1,3)    ==  (0,[],[3])\n--    decimal (23,14)  ==  (1,[6],[4,2,8,5,7,1])\ndecimal :: Racional -> Decimal\ndecimal (a,b) = (parteEntera r, antePeriodo r, periodo r)\n    where r = reducido (a,b)\n\n-- ---------------------------------------------------------------------\n-- \u00a7 De decimal a racional                                            --\n-- ---------------------------------------------------------------------\n\n-- (digitosAnumero xs) es el n\u00famero correspondiente a la lista de\n-- d\u00edgitos xs. Por ejemplo,\n--    digitosAnumero [3,2,5]  ==  325\ndigitosAnumero :: [Integer] -> Integer\ndigitosAnumero = foldl (\\a y -> 10*a+y) 0\n\n-- 2\u00aa definici\u00f3n de digitosAnumero (por comprensi\u00f3n)\ndigitosAnumero2 :: [Integer] -> Integer\ndigitosAnumero2 xs = sum [x*(10^i) | (x,i) <- zip xs [n-1,n-2..0]]\n    where n = length xs\n\n-- (racional (x,ys,zs)) es el n\u00famero racional cuya representaci\u00f3n\n-- decimal es (x,ys,zs). Por ejemplo,\n--    racional (0,[2,5],[])           ==  (1,4)\n--    racional (0,[],[3])             ==  (1,3)\n--    racional (1,[6],[4,2,8,5,7,1])  ==  (23,14)\nracional :: Decimal -> Racional\nracional (x,ys,[]) = reducido (a,b) where\n    a = digitosAnumero (x:ys)\n    b = 10^(length ys)\nracional (x,ys,zs) = reducido (a,b) where \n    a = digitosAnumero (x:ys++zs) - digitosAnumero (x:ys)\n    b = digitosAnumero (replicate (length zs) 9 ++ replicate (length ys) 0)\n\n-- ---------------------------------------------------------------------\n-- \u00a7 Propiedades                                                      --\n-- ---------------------------------------------------------------------\n\n-- La 1\u00aa propiedad es\nprop_RacionalDecimal :: Racional -> Property\nprop_RacionalDecimal (a,b) =\n    a >= 0 && b > 0  ==>\n    racional (decimal (a,b)) == reducido (a,b)\n\n-- La comprobaci\u00f3n es \n--    ghci> quickCheck prop_RacionalDecimal\n--    +++ OK, passed 100 tests.\n\n-- En lugar de reducido se puede usar un generador de n\u00fameros racionales\nnumeroRacional :: Gen Racional\nnumeroRacional = do a <- arbitrary\n                    b <- arbitrary\n                    return (reducido (abs a, 1+ abs b))\n\n-- La propiedad es\nprop_RacionalDecimal2 :: Property\nprop_RacionalDecimal2 =\n    forAll numeroRacional\n           (\\(a,b) -> racional (decimal (a,b)) == (a,b))\n\n-- La comprobaci\u00f3n es\n--   ghci> quickCheck prop_RacionalDecimal2\n--   +++ OK, passed 100 tests.\n\n-- Para la 2\u00aa propiedad se define un generador de n\u00fameros decimales\nnumeroDecimal :: Gen Decimal\nnumeroDecimal = do a <- arbitrary\n                   b <- arbitrary\n                   return (decimal (abs a, 1+ abs b))\n\n-- La 2\u00aa propiedad es\nprop_DecimalRacional :: Property\nprop_DecimalRacional =\n    forAll numeroDecimal \n           (\\(x,ys,zs) -> decimal (racional (x,ys,zs)) == (x,ys,zs))\n\n-- La comprobaci\u00f3n es\n--   ghci> quickCheck prop_DecimalRacional\n--   +++ OK, passed 100 tests.\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Continuando con los ejercicios propuestos por los alumnos, Antonio Garc\u00eda Bl\u00e1zquez ha propuesto un ejercicio que usa el per\u00edodo de los n\u00fameros decimales. El ejercicio de hoy, basado en su propuesta, trata de la representaci\u00f3n decimal de los n\u00fameros racionales. Los n\u00fameros decimales se representan por ternas, donde el primer elemento es la parte entera,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false},"categories":[7],"tags":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/1439"}],"collection":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/comments?post=1439"}],"version-history":[{"count":6,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/1439\/revisions"}],"predecessor-version":[{"id":6349,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/1439\/revisions\/6349"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/media?parent=1439"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/categories?post=1439"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/tags?post=1439"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}