lunes, 13 de marzo de 2023

Cálculo de pi mediante las series de Gregory-Leibniz y de Beeler

https://www.glc.us.es/~jalonso/exercitium/calculo-de-pi-mediante-los-metodos-de-gregory-leibniz-y-de-beeler/

Cálculo de pi mediante los métodos de Gregory-Leibniz y de Beeler

La fórmula de Gregory-Leibniz para calcular pi es
Calculo_de_pi_mediante_los_metodos_de_Gregory-Leibniz_y_de_Beeler_1
y la de Beeler es
Calculo_de_pi_mediante_los_metodos_de_Gregory-Leibniz_y_de_Beeler_2

Definir las funciones

   aproximaPiGL     :: Int -> Double
   aproximaPiBeeler :: Int -> Double
   graficas         :: [Int] -> IO ()

tales que

  • (aproximaPiGL n) es la aproximación de pi con los primeros n términos de la fórmula de Gregory-Leibniz. Por ejemplo,
     aproximaPiGL 1       ==  4.0
     aproximaPiGL 2       ==  2.666666666666667
     aproximaPiGL 3       ==  3.466666666666667
     aproximaPiGL 10      ==  3.0418396189294032
     aproximaPiGL 100     ==  3.1315929035585537
     aproximaPiGL 1000    ==  3.140592653839794
     aproximaPiGL 10000   ==  3.1414926535900345
     aproximaPiGL 100000  ==  3.1415826535897198
  • (aproximaPiBeeler n) es la aproximación de pi con los primeros n términos de la fórmula de Beeler. Por ejemplo,
     aproximaPiBeeler 1   ==  2.0
     aproximaPiBeeler 2   ==  2.6666666666666665
     aproximaPiBeeler 3   ==  2.933333333333333
     aproximaPiBeeler 10  ==  3.140578169680337
     aproximaPiBeeler 60  ==  3.141592653589793
     pi                   ==  3.141592653589793
  • (graficas xs) dibuja la gráfica de las k-ésimas aproximaciones de pi, donde k toma los valores de la lista xs, con las fórmulas de Gregory-Leibniz y de Beeler. Por ejemplo, (graficas [1..25]) dibuja
    Calculo_de_pi_mediante_los_metodos_de_Gregory-Leibniz_y_de_Beeler_3
    donde la línea morada corresponde a la aproximación de Gregory-Leibniz y la verde a la de Beeler.

Soluciones

import Graphics.Gnuplot.Simple
 
-- Definiciones de aproximaPiGL
-- ============================
 
-- 1ª definición de aproximaPiGL
aproximaPiGL :: Int -> Double
aproximaPiGL n = 4 * (sum . take n . sumaA . zipWith (/) [1,1..]) [1,3..]
  where sumaA (x:y:xs) = x:(-y):sumaA xs
 
-- 2ª definición de aproximaPiGL
aproximaPiGL2 :: Int -> Double
aproximaPiGL2 n =
  4 * (sum (take n (zipWith (/) (cycle [1,-1]) [1,3..])))
 
-- 3ª definición de aproximaPiGL
aproximaPiGL3 :: Int -> Double
aproximaPiGL3 n =
  4 * (sum . take n . zipWith (/) (cycle [1,-1])) [1,3..]
 
-- 4ª definición de aproximaPiGL
aproximaPiGL4 :: Int -> Double
aproximaPiGL4 n = serieGL !! (n-1)
 
serieGL :: [Double]
serieGL = scanl1 (+) (zipWith (/) numeradores denominadores)
  where numeradores   = cycle [4,-4]
        denominadores = [1,3..]
 
-- Definición de aproximaPiBeeler
aproximaPiBeeler :: Int -> Double
aproximaPiBeeler n = 2 * aux (fromIntegral n) 1
  where
    aux :: Double -> Double -> Double 
    aux n k | n == k    = 1
            | otherwise = 1 + (k/(2*k+1)) * aux n (1+k)
 
-- Definición de graficas
graficas :: [Int] -> IO ()
graficas xs = 
    plotLists [Key Nothing]
             [[(k,aproximaPiGL k)     | k <- xs],
              [(k,aproximaPiBeeler k) | k <- xs]]

Otras soluciones

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

4 soluciones de “Cálculo de pi mediante los métodos de Gregory-Leibniz y de Beeler

  1. juabaerui
    import Graphics.Gnuplot.Simple
     
    aproximaPiGL :: Int -> Double
    aproximaPiGL n =
      4 * sum [(-1)**(k+1)/(2*k-1) | k <- [1,2..fromIntegral (n)]]
     
    aproximaPiBeeler :: Int -> Double
    aproximaPiBeeler n =
      2 * aux [k/(2*k+1) | k <- [1.. fromIntegral (n-1)]]
      where aux []     = 1
            aux (x:xs) = 1 + x * aux xs
     
    graficas :: [Int] -> IO ()
    graficas xs =
      plotLists [ Key Nothing
                , Title "Aproximaciones de Pi: Gregory-Leibniz y de Beeler"]
                [map aproximaPiGL xs, map aproximaPiBeeler xs]
  2. rebgongor
    import Graphics.Gnuplot.Simple
     
    aproximaPiGL :: Int -> Double
    aproximaPiGL 1 = 4
    aproximaPiGL n
      | even n    = a - m
      | otherwise = a + m  
      where a =  aproximaPiGL (n-1)
            m = 4 / [3,5..] !! (n-2)
     
    aproximaPiBeeler :: Int -> Double
    aproximaPiBeeler n = 2 * foldr f 1 xs
      where f (a,b) xs = 1 + a/b * xs 
            xs         = [(x,2*x+1) | x <- [1..fromIntegral (n-1)]]
     
    graficas :: [Int] -> IO ()
    graficas xs =
      plotLists [Key Nothing, PNG "graficasGLyB.png"]
                [map aproximaPiGL xs, map aproximaPiBeeler xs]
  3. Enrique Zubiría
    import Graphics.Gnuplot.Simple
     
    aproximaPiGL :: Int -> Double
    aproximaPiGL n = 4 * (sum $ take n [(-1)**n/(2*n+1) | n <- [0..]])
     
    aproximaPiBeeler :: Int -> Double
    aproximaPiBeeler n = 2 * (aux n 1)
      where aux n m
              | n == 1    = 1
              | m == n-1  = 1 + m'/(2*m'+1)
              | otherwise = 1 + m'/(2*m'+1)*(aux n (m+1))
              where m' = fromIntegral m
     
    graficas :: [Int] -> IO ()
    graficas ns = 
      plotLists [Key Nothing, PNG "calculoPiLeibnizBeeler.png"]
                [map aproximaPiGL ns, map aproximaPiBeeler ns]
  4. javjimord

    Otra forma de calcular la aproximación de Gregory-Leibniz:

    terminosPiGL :: [Double]
    terminosPiGL = [((-1)**n) * (1/m) | (n,m) <- zip [0..] [1,3..]]
     
    aproximaPiGL :: Int -> Double
    aproximaPiGL n = 4 * (sum $ take n terminosPiGL)


No hay comentarios:

Publicar un comentario