{"id":1235,"date":"2011-02-21T12:01:06","date_gmt":"2011-02-21T12:01:06","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=1235"},"modified":"2011-02-24T06:02:21","modified_gmt":"2011-02-24T06:02:21","slug":"i1m2010-ejercicios-de-haskell-relacion-19","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/i1m2010-ejercicios-de-haskell-relacion-19\/","title":{"rendered":"I1M2010: Ejercicios de Haskell (relaci\u00f3n 19)"},"content":{"rendered":"<p>En la clase de hoy de <a href=\"http:\/\/www.cs.us.es\/~jalonso\/cursos\/i1m-10\">Inform\u00e1tica de 1\u00ba del Grado en Matem\u00e1ticas<\/a> hemos comentado la resoluci\u00f3n de ejercicios de las relaci\u00f3n 19 cuyas soluciones se muestran a continuaci\u00f3n.<br \/>\n<!--more--><\/p>\n<pre lang=\"haskell\">\r\n-- ---------------------------------------------------------------------\r\n-- Importaci\u00f3n de librer\u00edas                                           --\r\n-- ---------------------------------------------------------------------\r\n\r\nimport Test.QuickCheck\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Diferenciaci\u00f3n num\u00e9rica                                            --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1.1. Definir la funci\u00f3n\r\n--    derivada :: Double -> (Double -> Double) -> Double -> Double\r\n-- tal que (derivada a f x) es el valor de la derivada de la funci\u00f3n f\r\n-- en el punto x con aproximaci\u00f3n a. Por ejemplo, \r\n--    derivada 0.001 sin pi  ==  -0.9999998333332315\r\n--    derivada 0.001 cos pi  ==  4.999999583255033e-4\r\n-- ---------------------------------------------------------------------\r\n\r\nderivada :: Double -> (Double -> Double) -> Double -> Double\r\nderivada a f x = (f(x+a)-f(x))\/a  \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1.2. Definir las funciones\r\n--    derivadaBurda :: (Double -> Double) -> Double -> Double\r\n--    derivadaFina  :: (Double -> Double) -> Double -> Double\r\n--    derivadaSuper :: (Double -> Double) -> Double -> Double\r\n-- tales que \r\n--    * (derivadaBurda f x) es el valor de la derivada de la funci\u00f3n f \r\n--      en el punto x con aproximaci\u00f3n 0.01,\r\n--    * (derivadaFina f x) es el valor de la derivada de la funci\u00f3n f \r\n--      en el punto x con aproximaci\u00f3n 0.0001.\r\n--    * (derivadauperBurda f x) es el valor de la derivada de la funci\u00f3n f \r\n--      en el punto x con aproximaci\u00f3n 0.000001.\r\n-- Por ejemplo,\r\n--    derivadaBurda cos pi  ==  4.999958333473664e-3\r\n--    derivadaFina  cos pi  ==  4.999999969612645e-5\r\n--    derivadaSuper cos pi  ==  5.000444502911705e-7\r\n-- ---------------------------------------------------------------------\r\n\r\nderivadaBurda :: (Double -> Double) -> Double -> Double\r\nderivadaBurda = derivada 0.01  \r\n\r\nderivadaFina :: (Double -> Double) -> Double -> Double\r\nderivadaFina  = derivada 0.0001  \r\n\r\nderivadaSuper :: (Double -> Double) -> Double -> Double\r\nderivadaSuper = derivada 0.000001  \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 1.3. Definir la funci\u00f3n\r\n--    derivadaFinaDelSeno :: Double -> Double\r\n-- tal que (derivadaFinaDelSeno x) es el valor de la derivada fina del\r\n-- seno en x. Por ejemplo,\r\n--    derivadaFinaDelSeno pi  ==  -0.9999999983354436\r\n-- ---------------------------------------------------------------------\r\n\r\nderivadaFinaDelSeno :: Double -> Double\r\nderivadaFinaDelSeno = derivadaFina sin  \r\n\r\n-- ---------------------------------------------------------------------\r\n-- C\u00e1lculo de la ra\u00edz cuadrada                                        --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 2.1. En los siguientes apartados de este ejercicio se va a\r\n-- calcular la ra\u00edz cuadrada de un n\u00famero bas\u00e1ndose en las siguientes\r\n-- propiedades:\r\n-- * Si y es una aproximaci\u00f3n de la ra\u00edz cuadrada de x, entonces \r\n--   (y+x\/y)\/2 es una aproximaci\u00f3n mejor. \r\n-- * El l\u00edmite de la sucesi\u00f3n definida por \r\n--       x_0     = 1 \r\n--       x_{n+1} = (x_n+x\/x_n)\/2\r\n--   es la ra\u00edz cuadrada de x.\r\n-- \r\n-- Definir, por iteraci\u00f3n con until, la funci\u00f3n\r\n--    raiz :: Double -> Double\r\n-- tal que (raiz x) es la ra\u00edz cuadrada de x calculada usando la\r\n-- propiedad anterior con una aproximaci\u00f3n de 0.00001 y tomando como\r\n-- v. Por ejemplo, \r\n--    raiz 9  ==  3.000000001396984\r\n-- ---------------------------------------------------------------------\r\n\r\nraiz :: Double -> Double\r\nraiz x = raiz' 1\r\n    where raiz' y | aceptable y = y\r\n                  | otherwise   = raiz' (mejora y)\r\n          mejora y    = 0.5*(y+x\/y)\r\n          aceptable y = abs(y*y-x) < 0.00001\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.2. Definir el operador \r\n--    (~=) :: Double -> Double -> Bool\r\n-- tal que (x ~= y) si |x-y| < 0.001. Por ejemplo,\r\n--    3.05 ~= 3.07        ==  False\r\n--    3.00005 ~= 3.00007  == True\r\n-- ---------------------------------------------------------------------\r\n\r\ninfix 5 ~=\r\n(~=) :: Double -> Double -> Bool\r\nx ~= y = abs(x-y) < 0.001\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.3. Comprobar con QuickCheck que si x es positivo,\r\n-- entonces \r\n--    (raiz x)^2 ~= x\r\n-- ---------------------------------------------------------------------\r\n\r\n-- La propiedad es\r\nprop_raiz :: Double -> Bool\r\nprop_raiz x =\r\n    (raiz x')^2 ~= x'\r\n    where x' = abs x\r\n\r\n-- La comprobaci\u00f3n es\r\n--    *Main> quickCheck prop_raiz\r\n--    OK, passed 100 tests.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.4. Definir por recursi\u00f3n la funci\u00f3n\r\n--    until' :: (a -> Bool) -> (a -> a) -> a -> a\r\n-- tal que (until' p f x) es el resultado de aplicar la funci\u00f3n f a x el\r\n-- menor n\u00famero posible de veces, hasta alcanzar un valor que satisface\r\n-- el predicado p. Por ejemplo, \r\n--    until' (>1000) (2*) 1  ==  1024\r\n-- Nota: until' es equivalente a la predefinida until.\r\n-- ---------------------------------------------------------------------\r\n\r\nuntil' :: (a -> Bool) -> (a -> a) -> a -> a\r\nuntil' p f x  | p x       = x\r\n              | otherwise = until' p f (f x)\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.5. Definir, por iteraci\u00f3n con until, la funci\u00f3n\r\n--    raizI :: Double -> Double\r\n-- tal que (raizI x) es la ra\u00edz cuadrada de x calculada usando la\r\n-- propiedad anterior. Por ejemplo, \r\n--    raizI 9  ==  3.000000001396984\r\n-- ---------------------------------------------------------------------\r\n\r\nraizI :: Double -> Double\r\nraizI x = until aceptable mejora 1\r\n          where mejora y    = 0.5*(y+x\/y)\r\n                aceptable y = abs(y*y-x) < 0.00001\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 3.6. Comprobar con QuickCheck que si x es positivo,\r\n-- entonces \r\n--    (raizI x)^2 ~= x\r\n-- ---------------------------------------------------------------------\r\n\r\n-- La propiedad es\r\nprop_raizI :: Double -> Bool\r\nprop_raizI x =\r\n    (raizI x')^2 ~= x'\r\n    where x' = abs x           \r\n\r\n-- La comprobaci\u00f3n es\r\n--    *Main> quickCheck prop_raizI\r\n--    OK, passed 100 tests.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ceros de una funci\u00f3n                                               --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4. Los ceros de una funci\u00f3n pueden calcularse mediante el\r\n-- m\u00e9todo de Newton bas\u00e1ndose en las siguientes propiedades:\r\n-- * Si b es una aproximaci\u00f3n para el punto cero de f, entonces \r\n--   b-f(b)\/f'(b) es una mejor aproximaci\u00f3n.\r\n-- * el l\u00edmite de la sucesi\u00f3n x_n definida por\r\n--      x_0     = 1 \r\n--      x_{n+1} = x_n-f(x_n)\/f'(x_n)\r\n--   es un cero de f.\r\n-- ---------------------------------------------------------------------\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4.1. Definir por recursi\u00f3n la funci\u00f3n\r\n--    puntoCero :: (Double -> Double) -> Double\r\n-- tal que (puntoCero f) es un cero de la funci\u00f3n f calculado usando la\r\n-- propiedad anterior. Por ejemplo, \r\n--    puntoCero cos  ==  1.5707963267949576\r\n-- ---------------------------------------------------------------------\r\n\r\npuntoCero :: (Double -> Double) -> Double\r\npuntoCero f = puntoCero' f 1\r\n    where puntoCero' f x | aceptable x = x\r\n                         | otherwise   = puntoCero' f (mejora x)\r\n          mejora b    = b - f b \/ derivadaFina f b\r\n          aceptable b = abs (f b) < 0.00001\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 4.2. Definir, por iteraci\u00f3n con until, la funci\u00f3n\r\n--    puntoCeroI :: (Double -> Double) -> Double\r\n-- tal que (puntoCeroI f) es un cero de la funci\u00f3n f calculado usando la\r\n-- propiedad anterior. Por ejemplo, \r\n--    puntoCeroI cos  ==  1.5707963267949576\r\n-- ---------------------------------------------------------------------\r\n\r\npuntoCeroI :: (Double -> Double) -> Double\r\npuntoCeroI f = until aceptable mejora 1\r\n    where mejora b    = b - f b \/ derivadaFina f b\r\n          aceptable b = abs (f b) < 0.00001\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Funciones inversas                                                 --\r\n-- ---------------------------------------------------------------------\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5. En este ejercicio se usar\u00e1 la funci\u00f3n puntoCero para\r\n-- definir la inversa de distintas funciones.\r\n-- ---------------------------------------------------------------------\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.1. Definir, usando puntoCero, la funci\u00f3n\r\n--    raizCuadrada :: Double -> Double\r\n-- tal que (raizCuadrada x) es la ra\u00edz cuadrada de x. Por ejemplo,\r\n--    raizCuadrada 9  ==  3.000000002941184\r\n-- ---------------------------------------------------------------------\r\n\r\nraizCuadrada :: Double -> Double\r\nraizCuadrada a = puntoCero f\r\n    where f x = x*x-a  \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.2. Comprobar con QuickCheck que si x es positivo,\r\n-- entonces \r\n--    (raizCuadrada x)^2 ~= x\r\n-- ---------------------------------------------------------------------\r\n\r\n-- La propiedad es\r\nprop_raizCuadrada :: Double -> Bool\r\nprop_raizCuadrada x =\r\n    (raizCuadrada x')^2 ~= x'\r\n    where x' = abs x\r\n\r\n-- La comprobaci\u00f3n es\r\n--    *Main> quickCheck prop_raizCuadrada\r\n--    OK, passed 100 tests.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.3. Definir, usando puntoCero, la funci\u00f3n\r\n--    raizCubica :: Double -> Double\r\n-- tal que (raizCubica x) es la ra\u00edz cuadrada de x. Por ejemplo,\r\n--    raizCubica 27  ==  3.0000000000196048\r\n-- ---------------------------------------------------------------------\r\n\r\nraizCubica :: Double -> Double\r\nraizCubica a = puntoCero f\r\n    where f x = x*x*x-a \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.4. Comprobar con QuickCheck que si x es positivo,\r\n-- entonces \r\n--    (raizCubica x)^3 ~= x\r\n-- ---------------------------------------------------------------------\r\n\r\n-- La propiedad es\r\nprop_raizCubica :: Double -> Bool\r\nprop_raizCubica x =\r\n    (raizCubica x)^3 ~= x\r\n    where x' = abs x\r\n\r\n-- La comprobaci\u00f3n es\r\n--    *Main> quickCheck prop_raizCubica\r\n--    OK, passed 100 tests.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.5. Definir, usando puntoCero, la funci\u00f3n\r\n--    arcoseno :: Double -> Double\r\n-- tal que (arcoseno x) es el arcoseno de x. Por ejemplo,\r\n--    arcoseno 1  == 1.5665489428306574\r\n-- ---------------------------------------------------------------------\r\n\r\narcoseno :: Double -> Double\r\narcoseno a = puntoCero f\r\n    where f x = sin x - a  \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.6. Comprobar con QuickCheck que si x est\u00e1 entre 0 y 1,\r\n-- entonces \r\n--    sin (arcoseno x) ~= x\r\n-- ---------------------------------------------------------------------\r\n\r\n-- La propiedad es\r\nprop_arcoseno :: Double -> Bool\r\nprop_arcoseno x =\r\n    sin (arcoseno x') ~= x'\r\n    where x' = abs (x - fromIntegral (truncate x))\r\n\r\n-- La comprobaci\u00f3n es\r\n--    *Main> quickCheck prop_arcoseno\r\n--    OK, passed 100 tests.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.7. Definir, usando puntoCero, la funci\u00f3n\r\n--    arcocoseno :: Double -> Double\r\n-- tal que (arcoseno x) es el arcoseno de x. Por ejemplo,\r\n--    arcocoseno 0  == 1.5707963267949576\r\n-- ---------------------------------------------------------------------\r\n\r\narcocoseno :: Double -> Double\r\narcocoseno a = puntoCero f\r\n    where f x = cos x - a  \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.8. Comprobar con QuickCheck que si x est\u00e1 entre 0 y 1,\r\n-- entonces \r\n--    cos (arcocoseno x) ~= x\r\n-- ---------------------------------------------------------------------\r\n\r\n-- La propiedad es\r\nprop_arcocoseno :: Double -> Bool\r\nprop_arcocoseno x =\r\n    cos (arcocoseno x') ~= x'\r\n    where x' = abs (x - fromIntegral (truncate x))\r\n\r\n-- La comprobaci\u00f3n es\r\n--    *Main> quickCheck prop_arcocoseno\r\n--    OK, passed 100 tests.\r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.7. Definir, usando puntoCero, la funci\u00f3n\r\n--    inversa :: (Double -> Double) -> Double -> Double\r\n-- tal que (inversa g x) es el valor de la inversa de g en x. Por\r\n-- ejemplo, \r\n--    inversa (^2) 9  ==  3.000000002941184\r\n-- ---------------------------------------------------------------------\r\n\r\ninversa :: (Double -> Double) -> Double -> Double\r\ninversa g a = puntoCero f\r\n    where f x = g x - a  \r\n\r\n-- ---------------------------------------------------------------------\r\n-- Ejercicio 5.8. Redefinir, usando inversa, las funciones raizCuadrada,\r\n-- raizCubica, arcoseno y arcocoseno.\r\n-- ---------------------------------------------------------------------\r\n\r\nraizCuadrada' = inversa (^2)\r\nraizCubica'   = inversa (^3)\r\narcoseno'     = inversa sin  \r\narcocoseno'   = inversa cos\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>En la clase de hoy de Inform\u00e1tica de 1\u00ba del Grado en Matem\u00e1ticas hemos comentado la resoluci\u00f3n de ejercicios de las relaci\u00f3n 19 cuyas soluciones se muestran a continuaci\u00f3n.<\/p>\n","protected":false},"author":2,"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":[1],"tags":[287],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":false,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/1235"}],"collection":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/comments?post=1235"}],"version-history":[{"count":2,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/1235\/revisions"}],"predecessor-version":[{"id":1237,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/1235\/revisions\/1237"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=1235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=1235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=1235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}