Cálculo de pi mediante los métodos de Gregory-Leibniz y de Beeler
La fórmula de Gregory-Leibniz para calcular pi es
y la de Beeler es
Definir las funciones
1 2 3 |
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,
1 2 3 4 5 6 7 8 |
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,
1 2 3 4 5 6 |
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
donde la línea morada corresponde a la aproximación de Gregory-Leibniz y la verde a la de Beeler.
Soluciones
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
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>
Otra forma de calcular la aproximación de Gregory-Leibniz: