{"id":8344,"date":"2023-11-29T06:00:49","date_gmt":"2023-11-29T04:00:49","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/?p=8344"},"modified":"2024-05-17T18:42:22","modified_gmt":"2024-05-17T16:42:22","slug":"29-nov-23","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/29-nov-23\/","title":{"rendered":"Integraci\u00f3n por el m\u00e9todo de los rect\u00e1ngulos"},"content":{"rendered":"<p><br \/>\nLa integral definida de una funci\u00f3n f entre los l\u00edmites a y b puede calcularse mediante la regla del rect\u00e1ngulo (ver en http:\/\/bit.ly\/1FDhZ1z) usando la f\u00f3rmula<br \/>\n&#92;[ h(f(a+&#92;frac{h}{2}) + f(a+h+&#92;frac{h}{2}) + f(a+2h+&#92;frac{h}{2}) + &#8230; + f(a+nh+&#92;frac{h}{2}))&#92;]<br \/>\ncon &#92;(a+nh+&#92;dfrac{h}{2} &#92;leq b &lt; a+(n+1)h+&#92;dfrac{h}{2}&#92;) y usando valores peque\u00f1os para &#92;(h&#92;).<\/p>\n<p>Definir la funci\u00f3n<\/p>\n<pre lang=\"text\">\n   integral :: (Fractional a, Ord a) => a -> a -> (a -> a) -> a -> a\n<\/pre>\n<p>tal que <code>integral a b f h<\/code> es el valor de dicha expresi\u00f3n. Por ejemplo, el c\u00e1lculo de la integral de &#40;f(x) = x^3&#41; entre 0 y 1, con paso 0.01, es<\/p>\n<pre lang=\"text\">\n   integral 0 1 (^3) 0.01  ==  0.24998750000000042\n<\/pre>\n<p>Otros ejemplos son<\/p>\n<pre lang=\"text\">\n   integral 0 1 (^4) 0.01                        ==  0.19998333362500048\n   integral 0 1 (\\x -> 3*x^2 + 4*x^3) 0.01       ==  1.9999250000000026\n   log 2 - integral 1 2 (\\x -> 1\/x) 0.01         ==  3.124931644782336e-6\n   pi - 4 * integral 0 1 (\\x -> 1\/(x^2+1)) 0.01  ==  -8.333333331389525e-6\n<\/pre>\n<p><!--more--><\/p>\n<p><b>Soluciones<\/b><\/p>\n<p>A continuaci\u00f3n se muestran las <a href=\"#haskell\">soluciones en Haskell<\/a> y las <a href=\"#python\">soluciones en Python<\/a>.<\/p>\n<p><a name=\"haskell\"><\/a><br \/>\n<b>Soluciones en Haskell<\/b><\/p>\n<pre lang=\"haskell\">\nmodule Integracion_por_rectangulos where\n\nimport Test.Hspec (Spec, hspec, it, shouldBe, shouldSatisfy)\n\n-- 1\u00aa soluci\u00f3n\n-- ===========\n\nintegral :: (Fractional a, Ord a) => a -> a -> (a -> a) -> a -> a\nintegral a b f h = h * suma (a+h\/2) b (+h) f\n\n-- (suma a b s f) es l valor de\n--    f(a) + f(s(a)) + f(s(s(a)) + ... + f(s(...(s(a))...))\n-- hasta que s(s(...(s(a))...)) > b. Por ejemplo,\n--    suma 2 5 (1+) (^3)  ==  224\nsuma :: (Ord t, Num a) => t -> t -> (t -> t) -> (t -> a) -> a\nsuma a b s f = sum [f x | x <- sucesion a b s]\n\n-- (sucesion x y s) es la lista\n--    [a, s(a), s(s(a), ..., s(...(s(a))...)]\n-- hasta que s(s(...(s(a))...)) > b. Por ejemplo,\n--    sucesion 3 20 (+2)  ==  [3,5,7,9,11,13,15,17,19]\nsucesion :: Ord a => a -> a -> (a -> a) -> [a]\nsucesion a b s = takeWhile (<=b) (iterate s a)\n\n-- 2\u00aa soluci\u00f3n\n-- ===========\n\nintegral2 :: (Fractional a, Ord a) => a -> a -> (a -> a) -> a -> a\nintegral2 a b f h\n  | a+h\/2 > b = 0\n  | otherwise = h * f (a+h\/2) + integral2 (a+h) b f h\n\n-- 3\u00aa soluci\u00f3n\n-- ===========\n\nintegral3 :: (Fractional a, Ord a) => a -> a -> (a -> a) -> a -> a\nintegral3 a b f h = aux a where\n  aux x | x+h\/2 > b = 0\n        | otherwise = h * f (x+h\/2) + aux (x+h)\n\n-- Comparaci\u00f3n de eficiencia\n--    \u03bb> integral 0 10 (^3) 0.00001\n--    2499.9999998811422\n--    (4.62 secs, 1084774336 bytes)\n--    \u03bb> integral2 0 10 (^3) 0.00001\n--    2499.999999881125\n--    (7.90 secs, 1833360768 bytes)\n--    \u03bb> integral3 0 10 (^3) 0.00001\n--    2499.999999881125\n--    (7.27 secs, 1686056080 bytes)\n\n-- Verificaci\u00f3n\n-- ============\n\nverifica :: IO ()\nverifica = hspec spec\n\nspec :: Spec\nspec = do\n  it \"e1\" $\n    integral' 0 1 (^(3::Int)) 0.01 `shouldBe` 0.24998750000000042\n  it \"e2\" $\n    integral' 0 1 (^(4::Int)) 0.01 `shouldBe` 0.19998333362500048\n  it \"e3\" $\n    integral' 0 1 (\\x -> 3*x^(2::Int) + 4*x^(3::Int)) 0.01 `shouldBe` 1.9999250000000026\n  it \"e4\" $\n    log 2 - integral' 1 2 (1 \/) 0.01 `shouldBe` 3.124931644782336e-6\n  it \"e5\" $\n    pi - 4 * integral' 0 1 (\\x -> 1\/(x^(2::Int)+1)) 0.01 `shouldBe` -8.333333331389525e-6\n  it \"e1b\" $\n    integral2' 0 1 (^(3::Int)) 0.01 `shouldSatisfy` (~= 0.24998750000000042)\n  it \"e2b\" $\n    integral2' 0 1 (^(4::Int)) 0.01 `shouldSatisfy` (~= 0.19998333362500048)\n  it \"e3b\" $\n    integral2' 0 1 (\\x -> 3*x^(2::Int) + 4*x^(3::Int)) 0.01 `shouldSatisfy` (~= 1.9999250000000026)\n  it \"e4b\" $\n    log 2 - integral2' 1 2 (1 \/) 0.01 `shouldSatisfy` (~= 3.124931644782336e-6)\n  it \"e5b\" $\n    pi - 4 * integral2' 0 1 (\\x -> 1\/(x^(2::Int)+1)) 0.01 `shouldSatisfy` (~= (-8.333333331389525e-6))\n  it \"e1c\" $\n    integral3' 0 1 (^(3::Int)) 0.01 `shouldSatisfy` (~= 0.24998750000000042)\n  it \"e2c\" $\n    integral3' 0 1 (^(4::Int)) 0.01 `shouldSatisfy` (~= 0.19998333362500048)\n  it \"e3c\" $\n    integral3' 0 1 (\\x -> 3*x^(2::Int) + 4*x^(3::Int)) 0.01 `shouldSatisfy` (~= 1.9999250000000026)\n  it \"e4c\" $\n    log 2 - integral3' 1 2 (1 \/) 0.01 `shouldSatisfy` (~= 3.124931644782336e-6)\n  it \"e5c\" $\n    pi - 4 * integral3' 0 1 (\\x -> 1\/(x^(2::Int)+1)) 0.01 `shouldSatisfy` (~= (-8.333333331389525e-6))\n  where\n    integral', integral2', integral3' :: Double -> Double -> (Double -> Double) -> Double -> Double\n    integral'  = integral\n    integral2' = integral2\n    integral3' = integral3\n    a ~= b = abs (a - b) < 0.00001\n\n-- La verificaci\u00f3n es\n--    \u03bb> verifica\n--\n--    Finished in 0.0058 seconds\n--    15 examples, 0 failures\n<\/pre>\n<p><a name=\"python\"><\/a><br \/>\n<b>Soluciones en Python<\/b><\/p>\n<pre lang=\"python\">\nfrom math import log, pi\nfrom typing import Callable\n\n# 1\u00aa soluci\u00f3n\n# ===========\n\n# sucesion(x, y, s) es la lista\n#    [a, s(a), s(s(a), ..., s(...(s(a))...)]\n# hasta que s(s(...(s(a))...)) > b. Por ejemplo,\n#    sucesion(3, 20, lambda x : x+2)  ==  [3,5,7,9,11,13,15,17,19]\ndef sucesion(a: float, b: float, s: Callable[[float], float]) -> list[float]:\n    xs = []\n    while a <= b:\n        xs.append(a)\n        a = s(a)\n    return xs\n\n# suma(a, b, s, f) es el valor de\n#    f(a) + f(s(a)) + f(s(s(a)) + ... + f(s(...(s(a))...))\n# hasta que s(s(...(s(a))...)) > b. Por ejemplo,\n#    suma(2, 5, lambda x: x+1, lambda x: x**3)  ==  224\ndef suma(a: float,\n         b: float,\n         s: Callable[[float], float],\n         f: Callable[[float], float]) -> float:\n    return sum(f(x) for x in sucesion(a, b, s))\n\ndef integral(a: float,\n             b: float,\n             f: Callable[[float], float],\n             h: float) -> float:\n    return h * suma(a+h\/2, b, lambda x: x+h, f)\n\n# 2\u00aa soluci\u00f3n\n# ===========\n\ndef integral2(a: float,\n              b: float,\n              f: Callable[[float], float],\n              h: float) -> float:\n    if a+h\/2 > b:\n        return 0\n    return h * f(a+h\/2) + integral2(a+h, b, f, h)\n\n# 3\u00aa soluci\u00f3n\n# ===========\n\ndef integral3(a: float,\n              b: float,\n              f: Callable[[float], float],\n              h: float) -> float:\n    def aux(x: float) -> float:\n        if x+h\/2 > b:\n            return 0\n        return h * f(x+h\/2) + aux(x+h)\n    return aux(a)\n\n# Verificaci\u00f3n\n# ============\n\ndef test_integral() -> None:\n    def aproximado(a: float, b: float) -> bool:\n        return abs(a - b) < 0.00001\n    assert integral(0, 1, lambda x : x**3, 0.01) == 0.24998750000000042\n    assert integral(0, 1, lambda x : x**4, 0.01) == 0.19998333362500054\n    assert integral(0, 1, lambda x : 3*x**2 + 4*x**3, 0.01) == 1.9999250000000026\n    assert log(2) - integral(1, 2, lambda x : 1\/x, 0.01) == 3.124931644782336e-6\n    assert pi - 4 * integral(0, 1, lambda x : 1\/(x**2+1), 0.01) == -8.333333331389525e-6\n    assert aproximado(integral2(0, 1, lambda x : x**3, 0.01),\n                      0.24998750000000042)\n    assert aproximado(integral2(0, 1, lambda x : x**4, 0.01),\n                      0.19998333362500054)\n    assert aproximado(integral2(0, 1, lambda x : 3*x**2 + 4*x**3, 0.01),\n                      1.9999250000000026)\n    assert aproximado(log(2) - integral2(1, 2, lambda x : 1\/x, 0.01),\n                      3.124931644782336e-6)\n    assert aproximado(pi - 4 * integral2(0, 1, lambda x : 1\/(x**2+1), 0.01),\n                      -8.333333331389525e-6)\n    assert aproximado(integral3(0, 1, lambda x : x**3, 0.01),\n                      0.24998750000000042)\n    assert aproximado(integral3(0, 1, lambda x : x**4, 0.01),\n                      0.19998333362500054)\n    assert aproximado(integral3(0, 1, lambda x : 3*x**2 + 4*x**3, 0.01),\n                      1.9999250000000026)\n    assert aproximado(log(2) - integral3(1, 2, lambda x : 1\/x, 0.01),\n                      3.124931644782336e-6)\n    assert aproximado(pi - 4 * integral3(0, 1, lambda x : 1\/(x**2+1), 0.01),\n                      -8.333333331389525e-6)\n    print(\"Verificado\")\n\n# La verificaci\u00f3n es\n#    >>> test_integral()\n#    Verificado\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>La integral definida de una funci\u00f3n f entre los l\u00edmites a y b puede calcularse mediante la regla del rect\u00e1ngulo (ver en http:\/\/bit.ly\/1FDhZ1z) usando la f\u00f3rmula &#92;[ h(f(a+&#92;frac{h}{2}) + f(a+h+&#92;frac{h}{2}) + f(a+2h+&#92;frac{h}{2}) + &#8230; + f(a+nh+&#92;frac{h}{2}))&#92;] con &#92;(a+nh+&#92;dfrac{h}{2} &#92;leq b &lt; a+(n+1)h+&#92;dfrac{h}{2}&#92;) y usando valores peque\u00f1os para &#92;(h&#92;). Definir la funci\u00f3n integral :: (Fractional a,&#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":"default","_kad_post_title":"default","_kad_post_layout":"default","_kad_post_sidebar_id":"","_kad_post_content_style":"default","_kad_post_vertical_padding":"default","_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":[581],"tags":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/8344"}],"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=8344"}],"version-history":[{"count":6,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/8344\/revisions"}],"predecessor-version":[{"id":8570,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/8344\/revisions\/8570"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/media?parent=8344"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/categories?post=8344"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/tags?post=8344"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}