Menu Close

Cálculo de pi mediante la fórmula de Brouncker

El mes de marzo es el mes de pi, ya que el 14 de marzo (3/14) es el día de pi. Con ese motivo, el pasado 3 de marzo se publicó en Twitter un mensaje con la fórmula de Brouncker para el cálculo de pi

La primeras aproximaciones son

     a(1) = 4                                  =  4
     a(2) = 4/(1+1^2)                          =  2.0
     a(3) = 4/(1+1^2/(2+3^2))                  =  3.666666666666667
     a(4) = 4/(1+1^2/(2+3^2/(2+5^2)))          =  2.8
     a(5) = 4/(1+1^2/(2+3^2/(2+5^2/(2+7^2))))  =  3.395238095238095

Definir las funciones

   aproximacionPi :: Int -> Double
   grafica        :: [Int] -> IO ()

tales que

  • (aproximacionPi n) es la n-ésima aproximación de pi con la fórmula de Brouncker. Por ejemplo,
     aproximacionPi 1      ==  4.0
     aproximacionPi 2      ==  2.0
     aproximacionPi 3      ==  3.666666666666667
     aproximacionPi 4      ==  2.8
     aproximacionPi 5      ==  3.395238095238095
     aproximacionPi 10     ==  3.0301437124966535
     aproximacionPi 1000   ==  3.1405916523380406
     aproximacionPi 1001   ==  3.142592653839793
     aproximacionPi 10000  ==  3.141492643588543
     aproximacionPi 10001  ==  3.1416926535900433
     pi                    ==  3.141592653589793
  • (grafica xs) dibuja la gráfica de las k-ésimas aproximaciones de pi para k en xs. Por ejemplo, (grafica [10..100]) dibuja

Soluciones

import Graphics.Gnuplot.Simple (Attribute (Key, PNG), plotList)
 
-- 1ª solución
-- ===========
 
aproximacionPi :: Int -> Double
aproximacionPi 1 = 4
aproximacionPi n = 4/(1 + 1/(aux 1 3))
  where aux a b | a == n-1  = 1
                | otherwise = 2 + (b^2)/(aux (a+1) (b+2))
 
-- El cálculo es
--    aproximacionPi 2
--      = 4/(1 + 1/(aux 1 3))
--      = 4/(1 + 1/1)
--      = 2.0
--
--    aproximacionPi 3
--      = 4/(1 + 1/(aux 1 3))
--      = 4/(1 + 1/(2 + 3^2/(aux 2 5))
--      = 4/(1 + 1/(2 + 3^2/1))
--      = 3.666666666666667
--
--    aproximacionPi 4
--      = 4/(1 + 1/(aux 1 3))
--      = 4/(1 + 1/(2 + 3^2/(aux 2 5))
--      = 4/(1 + 1/(2 + 3^2/(2 + 5^2/(aux 3 7))))
--      = 4/(1 + 1/(2 + 3^2/(2 + 5^2/1)))
--      = 2.8
 
-- 2ª solución
-- ===========
 
aproximacionPi2 :: Int -> Double
aproximacionPi2 n =
  aproximacionFC n fraccionPi
 
-- fraccionPi es la representación de la fracción continua de pi como un
-- par de listas infinitas.
fraccionPi :: [(Integer, Integer)]
fraccionPi = zip (0 : 1 : [2,2..]) (4 : map (^2) [1,3..])
 
-- (aproximacionFC n fc) es la n-ésima aproximación de la fracción
-- continua fc (como un par de listas).
aproximacionFC :: Int -> [(Integer, Integer)] -> Double
aproximacionFC n =
  foldr (\(a,b) z -> fromIntegral a + fromIntegral b / z) 1 . take n
 
-- Gráfica
-- =======
 
grafica :: [Int] -> IO ()
grafica xs =
  plotList [ Key Nothing
           -- , PNG "Calculo_de_pi_mediante_la_formula_de_Brouncker_1.png"
           ]
           [(k,aproximacionPi k) | k <- xs]

Nuevas soluciones

  • En los comentarios se pueden escribir nuevas soluciones.
  • El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>

5 soluciones de “Cálculo de pi mediante la fórmula de Brouncker

  1. Rubén Muñoz Mkrtchian
    import Graphics.Gnuplot.Simple
     
    aproximacionPi :: Int -> Double
    aproximacionPi 1 = 4
    aproximacionPi n = fraccionesSucesivas (4 : map (^2) [1,3..]) (1 : repeat 2) (fromIntegral (n-1))
     
    -- Dadas dos sucesiones de números xs e ys, la función fraccionesSucesivas
    -- dispone los números de dichas sucesiones de la forma en la que aparecen en
    -- la fórmula de Brouncker para el cálculo de pi.
     
    fraccionesSucesivas :: [Double] -> [Double] -> Double -> Double
    fraccionesSucesivas (x:xs) (y:ys) 0 = x
    fraccionesSucesivas (x:xs) (y:ys) n = x / (y + fraccionesSucesivas xs ys (n-1))
     
    -- Al usar plotList en el eje OX no se muestran correctamente los valores, por
    -- ejemplo, del 10 al 100, sino del 0 al 90. Pero al intentar usar plotFunc da
    -- el siguiente error de tipo:
    --   * Couldn't match type `Double' with `Int'
    --     Expected type: Int -> Int
    --       Actual type: Int -> Double
    -- Redefiniendo aproximacionPi, podemos obtener una función que vaya de un tipo
    -- en sí mismo para así solucionar el problema.
     
    aproximacionPi' :: Double -> Double
    aproximacionPi' 1 = 4
    aproximacionPi' n = fraccionesSucesivas (4 : map (^2) [1,3..]) (1 : repeat 2) (n-1)
     
    grafica :: [Int] -> IO ()
    grafica xs = plotFunc [Key Nothing] (map fromIntegral xs) aproximacionPi'
  2. Juan María Jiménez Jiménez
     
    aproximacionPi :: Int -> Double
    aproximacionPi 1 = 4
    aproximacionPi n = 4/(fraccionAux n)
     
    --La funcion fraccion, genera una fraccion a partir de dos listas de modo que la fraccion 
    --es el primer elemento de una de ellas, más el primer 
    --elemento de la otra entre la siguiente fraccion, 
    --tal y como vemos en la formula dada. 
     
    fraccion :: [Int] -> [Int] -> Int -> Double
    fraccion [] [] _ = 0
    fraccion xs ys 0 = 1
    fraccion xs ys 1 = 1
    fraccion xs ys n = x+(y/(fraccion xs' ys' (n-1)))
      where x = fromIntegral $ head xs
            y = fromIntegral $ head ys
            xs' = tail xs
            ys' = tail ys
     
    --fraccionAux nos da en concreto la fraccion continua que usamos en la formula que se nos da.
     
    fraccionAux :: Int -> Double
    fraccionAux n = fraccion (1:repeat 2) (map (^2) [1,3..]) n
     
    grafica :: [Int] -> IO ()
    grafica xs = plotList [Key Nothing] (map (aproximacionPi) xs)
  3. ADOLFO ENRIQUE VÁZQUEZ RUIZ
     
    aproximacionPi :: Int -> Double
    aproximacionPi n = 4/(aux (take (n-1) numeradores) (take (n-1) elementoSuma))
     
    aux :: [Double] -> [Double] -> Double
    aux [] []  = 1
    aux (x:xs) (y:ys) = (y + (x/(aux xs ys)))         
    --aux es una función recursiva que determina los sucesivos denominadores de la
    --fórmula de Brouncker empleando elementos de dos listas.
     
    numeradores :: [Double]
    numeradores = [ x^2 | x <- [1,3..]]
    --numeradores es una lista infinita formada por los sucesivos numeradores que
    --aparecen en la fórmula de Brouncker.
     
    elementoSuma :: [Double]
    elementoSuma = 1:(repeat 2)
    --elementoSuma es una lista infinita formada por los elementos que se suman a
    --las fracciones que aparecen en los sucesivo denominadores de la fórmula de
    --Brouncker. 
     
    grafica :: [Int] -> IO ()
    grafica xs = plotList [Key Nothing] (map (aproximacionPi) xs)
  4. Mercedes Vega Gallo
    import Graphics.Gnuplot.Simple
     
    aproximacionPi :: Int -> Double
    aproximacionPi n = aux (0:1:repeat 2) (4:map (^2) [1,3..]) 1
                       where aux (x:xs) (y:ys) i |i == n = x+y
                                                 |otherwise = x+y/(aux xs ys (i+1))
     
    grafica :: [Int] -> IO ()
    grafica xs = plotList [Title "APROXIMACION DE PI MEDIANTE LA FORMULA DE BROUNCKER", Key Nothing] (zip xs (map aproximacionPi xs))
  5. Alejandro García Alcaide
    import Graphics.Gnuplot.Simple
     
    aproximacionPi :: Int -> Double
    aproximacionPi n = 4 / (aproxFrac lista1 lista2 (n-1))
     
    -- Definimos una funcion auxiliar: 
    aproxFrac :: [Double] -> [Double] -> Int -> Double
    aproxFrac   []     []   _ = 0
    aproxFrac    _      _   0 = 1
    aproxFrac (x:xs) (y:ys) n =
      (x + y/aproxFrac xs ys (n-1))
     
    -- Definimos las dos listas que aparecen en la funcion auxiliar anterior.
    lista1 :: [Double]
    lista1 = 1 : repeat 2
     
    lista2 :: [Double]
    lista2 = [x^2 | x <- [1,3..]]
     
     
    grafica :: [Int] -> IO ()
    grafica xs = plotList [] (map aproximacionPi xs)

Leave a Reply

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.