{"id":7442,"date":"2022-10-14T06:00:09","date_gmt":"2022-10-14T04:00:09","guid":{"rendered":"http:\/\/www.glc.us.es\/~jalonso\/exercitium\/?p=7442"},"modified":"2022-12-14T12:32:37","modified_gmt":"2022-12-14T10:32:37","slug":"calculo-del-numero-%cf%80-mediante-la-formula-de-leibniz","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/calculo-del-numero-%cf%80-mediante-la-formula-de-leibniz\/","title":{"rendered":"C\u00e1lculo del n\u00famero \u03c0 mediante la f\u00f3rmula de Leibniz"},"content":{"rendered":"<p>El n\u00famero \u03c0 puede calcularse con la <a href=\"https:\/\/bit.ly\/3ERCwZd\">f\u00f3rmula de Leibniz<\/a><\/p>\n<pre lang=\"text\">\n   \u03c0\/4 = 1 - 1\/3 + 1\/5 - 1\/7 + ...+ (-1)**n\/(2*n+1) + ...\n<\/pre>\n<p>Definir las funciones<\/p>\n<pre lang=\"text\">\n   calculaPi :: Int -> Double\n   errorPi   :: Double -> Int\n<\/pre>\n<p>tales que<\/p>\n<ul>\n<li><code>calculaPi n<\/code> es la aproximaci\u00f3n del n\u00famero \u03c0 calculada mediante la expresi\u00f3n<\/li>\n<\/ul>\n<pre lang=\"text\">\n     4*(1 - 1\/3 + 1\/5 - 1\/7 + ...+ (-1)**n\/(2*n+1))\n<\/pre>\n<p>Por ejemplo,<\/p>\n<pre lang=\"text\">\n     calculaPi 3    ==  2.8952380952380956\n     calculaPi 300  ==  3.1449149035588526\n<\/pre>\n<ul>\n<li><code>errorPi x<\/code> es el menor n\u00famero de t\u00e9rminos de la serie necesarios para obtener pi con un error menor que <code>x<\/code>. Por ejemplo,<\/li>\n<\/ul>\n<pre lang=\"text\">\n     errorPi 0.1    ==    9\n     errorPi 0.01   ==   99\n     errorPi 0.001  ==  999\n<\/pre>\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\">\nimport Test.QuickCheck\n\n-- 1\u00aa definici\u00f3n de calculaPi\n-- ==========================\n\ncalculaPi1 :: Int -> Double\ncalculaPi1 k = 4 * sum [(-1)**n\/(2*n+1) | n <- [0..k']]\n  where k' = fromIntegral k\n\n-- 2\u00aa definici\u00f3n de calculaPi\n-- ==========================\n\ncalculaPi2 :: Int -> Double\ncalculaPi2 0 = 4\ncalculaPi2 n = calculaPi2 (n-1) + 4*(-1)**n'\/(2*n'+1)\n  where n' = fromIntegral n\n\n-- 3\u00aa definici\u00f3n de calculaPi\n-- ==========================\n\ncalculaPi3 :: Int -> Double\ncalculaPi3 = aux . fromIntegral\n  where aux 0 = 4\n        aux n = 4*(-1)**n\/(2*n+1) + aux (n-1)\n\n-- Comprobaci\u00f3n de equivalencia de calculaPi\n-- =========================================\n\n-- La propiedad es\nprop_calculaPi :: Positive Int -> Bool\nprop_calculaPi (Positive k) =\n  all (== calculaPi1 k)\n      [calculaPi2 k,\n       calculaPi3 k]\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_calculaPi\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia de calculaPi\n-- ======================================\n\n-- La comparaci\u00f3n es\n--    \u03bb> calculaPi1 (10^6)\n--    3.1415936535887745\n--    (1.31 secs, 609,797,408 bytes)\n--    \u03bb> calculaPi2 (10^6)\n--    3.1415936535887745\n--    (1.68 secs, 723,032,272 bytes)\n--    \u03bb> calculaPi3 (10^6)\n--    3.1415936535887745\n--    (2.22 secs, 1,099,032,608 bytes)\n\n\n-- 1\u00aa definici\u00f3n de errorPi\n-- ========================\n\nerrorPi1 :: Double -> Int\nerrorPi1 x =\n  head [n | n <- [1..]\n          , abs (pi - calculaPi1 n) < x]\n\n-- 2\u00aa definici\u00f3n de errorPi\n-- ========================\n\nerrorPi2 :: Double -> Int\nerrorPi2 x = aux 1\n  where aux n | abs (pi - calculaPi1 n) < x = n\n              | otherwise                   = aux (n+1)\n\n-- Comprobaci\u00f3n de equivalencia de errorPi\n-- ============================================\n\n-- La propiedad es\nprop_errorPi :: Positive Double -> Bool\nprop_errorPi (Positive x) =\n  errorPi1 x == errorPi2 x\n\n-- La comprobaci\u00f3n es\n--    \u03bb> quickCheck prop_errorPi\n--    +++ OK, passed 100 tests.\n\n-- Comparaci\u00f3n de eficiencia de errorPi\n-- ====================================\n\n-- La comparaci\u00f3n es\n--    \u03bb> errorPi1 0.0005\n--    1999\n--    (1.88 secs, 1,189,226,384 bytes)\n--    \u03bb> errorPi2 0.0005\n--    1999\n--    (1.87 secs, 1,213,341,096 bytes)\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium\/blob\/main\/src\/Calculo_de_pi_mediante_la_formula_de_Leibniz.hs\">GitHub<\/a>.<\/p>\n<p><a name=\"python\"><\/a><br \/>\n<b>Soluciones en Python<\/b><\/p>\n<pre lang=\"python\">\nfrom itertools import islice\nfrom math import pi\nfrom sys import setrecursionlimit\nfrom timeit import Timer, default_timer\nfrom typing import Iterator\n\nfrom hypothesis import given\nfrom hypothesis import strategies as st\n\nsetrecursionlimit(10**6)\n\n# 1\u00aa definici\u00f3n de calculaPi\n# ==========================\n\ndef calculaPi1(k: int) -> float:\n    return 4 * sum(((-1)**n\/(2*n+1) for n in range(0, k+1)))\n\n# 2\u00aa definici\u00f3n de calculaPi\n# ==========================\n\ndef calculaPi2(n: int) -> float:\n    if n == 0:\n        return 4\n    return calculaPi2(n-1) + 4*(-1)**n\/(2*n+1)\n\n# 3\u00aa definici\u00f3n de calculaPi\n# ==========================\n\ndef calculaPi3(n: int) -> float:\n    r = 1\n    for k in range(1, n+1):\n        r = r + (-1)**k\/(2*k+1)\n    return 4 * r\n\n# Comprobaci\u00f3n de equivalencia de calculaPi\n# =========================================\n\n# La propiedad es\n@given(st.integers(min_value=1, max_value=100))\ndef test_calculaPi(n: int) -> None:\n    r = calculaPi1(n)\n    assert calculaPi2(n) == r\n    assert calculaPi3(n) == r\n\n# La comprobaci\u00f3n es\n#    src> poetry run pytest -q calculo_de_pi_mediante_la_formula_de_Leibniz.py\n#    1 passed in 0.14s\n\n# Comparaci\u00f3n de eficiencia de calculaPi\n# ======================================\n\ndef tiempo(e: str) -> None:\n    \"\"\"Tiempo (en segundos) de evaluar la expresi\u00f3n e.\"\"\"\n    t = Timer(e, \"\", default_timer, globals()).timeit(1)\n    print(f\"{t:0.2f} segundos\")\n\n# La comparaci\u00f3n es\n#    >>> tiempo('calculaPi1(10**6)')\n#    0.37 segundos\n#    >>> tiempo('calculaPi2(10**6)')\n#    Process Python violaci\u00f3n de segmento (core dumped)\n#    >>> tiempo('calculaPi3(10**6)')\n#    0.39 segundos\n\n# 1\u00aa definici\u00f3n de errorPi\n# ========================\n\n# naturales es el generador de los n\u00fameros naturales positivos, Por\n# ejemplo,\n#    >>> list(islice(naturales(), 5))\n#    [1, 2, 3, 4, 5]\ndef naturales() -> Iterator[int]:\n    i = 1\n    while True:\n        yield i\n        i += 1\n\ndef errorPi1(x: float) -> int:\n    return list(islice((n for n in naturales()\n                        if abs(pi - calculaPi1(n)) < x), 1))[0]\n\n# 2\u00aa definici\u00f3n de errorPi\n# ========================\n\ndef errorPi2(x: float) -> int:\n    def aux(n: int) -> int:\n        if abs(pi - calculaPi1(n)) < x:\n            return n\n        return aux(n + 1)\n\n    return aux(1)\n\n# Comprobaci\u00f3n de equivalencia de errorPi\n# =======================================\n\n@given(st.integers(min_value=1, max_value=100))\ndef test_errorPi(n: int) -> None:\n    assert errorPi1(n) == errorPi2(n)\n\n# La comprobaci\u00f3n es\n#    src> poetry run pytest -q calculo_de_pi_mediante_la_formula_de_Leibniz.py\n#    2 passed in 0.60s\n\n# Comparaci\u00f3n de eficiencia de errorPi\n# ====================================\n\n# La comparaci\u00f3n es\n#    >>> tiempo('errorPi1(0.0005)')\n#    0.63 segundos\n#    >>> tiempo('errorPi2(0.0005)')\n#    0.58 segundos\n<\/pre>\n<p>El c\u00f3digo se encuentra en <a href=\"https:\/\/github.com\/jaalonso\/Exercitium-Python\/blob\/main\/src\/calculo_de_pi_mediante_la_formula_de_Leibniz.py\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>El n\u00famero \u03c0 puede calcularse con la f\u00f3rmula de Leibniz \u03c0\/4 = 1 &#8211; 1\/3 + 1\/5 &#8211; 1\/7 + &#8230;+ (-1)**n\/(2*n+1) + &#8230; Definir las funciones calculaPi :: Int -> Double errorPi :: Double -> Int tales que calculaPi n es la aproximaci\u00f3n del n\u00famero \u03c0 calculada mediante la expresi\u00f3n 4*(1 &#8211; 1\/3 +&#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":[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\/7442"}],"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=7442"}],"version-history":[{"count":2,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/7442\/revisions"}],"predecessor-version":[{"id":7670,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/posts\/7442\/revisions\/7670"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/media?parent=7442"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/categories?post=7442"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/exercitium\/wp-json\/wp\/v2\/tags?post=7442"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}