Menu Close

Cálculo de pi mediante la serie de Nilakantha

Una serie infinita para el cálculo de pi, publicada por Nilakantha en el siglo XV, es
Calculo_de_pi_mediante_la_serie_de_Nilakantha

Definir las funciones

   aproximacionPi :: Int -> Double
   tabla          :: FilePath -> [Int] -> IO ()

tales que

  • (aproximacionPi n) es la n-ésima aproximación de pi obtenido sumando los n primeros términos de la serie de Nilakantha. Por ejemplo,
     aproximacionPi 0        ==  3.0
     aproximacionPi 1        ==  3.1666666666666665
     aproximacionPi 2        ==  3.1333333333333333
     aproximacionPi 3        ==  3.145238095238095
     aproximacionPi 4        ==  3.1396825396825396
     aproximacionPi 5        ==  3.1427128427128426
     aproximacionPi 10       ==  3.1414067184965018
     aproximacionPi 100      ==  3.1415924109719824
     aproximacionPi 1000     ==  3.141592653340544
     aproximacionPi 10000    ==  3.141592653589538
     aproximacionPi 100000   ==  3.1415926535897865
     aproximacionPi 1000000  ==  3.141592653589787
     pi                      ==  3.141592653589793
  • (tabla f ns) escribe en el fichero f las n-ésimas aproximaciones de pi, donde n toma los valores de la lista ns, junto con sus errores. Por ejemplo, al evaluar la expresión
     tabla "AproximacionesPi.txt" [0,10..100]

hace que el contenido del fichero “AproximacionesPi.txt” sea

+------+----------------+----------------+
| n    | Aproximación   | Error          |
+------+----------------+----------------+
|    0 | 3.000000000000 | 0.141592653590 |
|   10 | 3.141406718497 | 0.000185935093 |
|   20 | 3.141565734659 | 0.000026918931 |
|   30 | 3.141584272675 | 0.000008380915 |
|   40 | 3.141589028941 | 0.000003624649 |
|   50 | 3.141590769850 | 0.000001883740 |
|   60 | 3.141591552546 | 0.000001101044 |
|   70 | 3.141591955265 | 0.000000698325 |
|   80 | 3.141592183260 | 0.000000470330 |
|   90 | 3.141592321886 | 0.000000331704 |
|  100 | 3.141592410972 | 0.000000242618 |
+------+----------------+----------------+

y al evaluar la expresión

     tabla "AproximacionesPi.txt" [0,500..5000]

hace que el contenido del fichero “AproximacionesPi.txt” sea

+------+----------------+----------------+
| n    | Aproximación   | Error          |
+------+----------------+----------------+
|    0 | 3.000000000000 | 0.141592653590 |
|  500 | 3.141592651602 | 0.000000001988 |
| 1000 | 3.141592653341 | 0.000000000249 |
| 1500 | 3.141592653516 | 0.000000000074 |
| 2000 | 3.141592653559 | 0.000000000031 |
| 2500 | 3.141592653574 | 0.000000000016 |
| 3000 | 3.141592653581 | 0.000000000009 |
| 3500 | 3.141592653584 | 0.000000000006 |
| 4000 | 3.141592653586 | 0.000000000004 |
| 4500 | 3.141592653587 | 0.000000000003 |
| 5000 | 3.141592653588 | 0.000000000002 |
+------+----------------+----------------+

Nota: Este ejercicio ha sido propuesto por Manuel Herrera.

Referencias

Soluciones

import Text.Printf
 
-- 1ª definición
-- =============
 
aproximacionPi :: Int -> Double
aproximacionPi n = serieNilakantha !! n
 
serieNilakantha :: [Double]
serieNilakantha = scanl1 (+) terminosNilakantha
 
terminosNilakantha :: [Double]
terminosNilakantha = zipWith (/) numeradores denominadores
  where numeradores   = 3 : cycle [4,-4]
        denominadores = 1 : [n*(n+1)*(n+2) | n <- [2,4..]]
 
tabla :: FilePath -> [Int] -> IO ()
tabla f ns = do
  writeFile f (tablaAux ns)
 
tablaAux :: [Int] -> String
tablaAux ns =
     linea
  ++ cabecera
  ++ linea
  ++ concat [printf "| %4d | %.12f | %.12f |\n" n a e
            | n <- ns
            , let a = aproximacionPi n
            , let e = abs (pi - a)]
  ++ linea
 
linea :: String
linea = "+------+----------------+----------------+\n"
 
cabecera :: String
cabecera = "| n    | Aproximación   | Error          |\n"

7 soluciones de “Cálculo de pi mediante la serie de Nilakantha

  1. albcercid
    aproximacionPi7 :: Int -> Double
    aproximacionPi7 x = 3 + aux [2..] (3*x)
         where aux _ 0 = 0
               aux (x:y:z:xs) n = 4/(x*y*z) - aux (z:xs) (n-3)
     
     
    tabla          :: FilePath -> [Int] -> IO ()
    tabla f ns = do
      writeFile f (tablaAux ns)
     
    tablaAux :: [Int] -> String
    tablaAux ns =
         linea
      ++ cabecera
      ++ linea
      ++ concat [printf "| %4d | %.12f | %.12f |n" n x z
                | n <- ns
                , let x = aproximacionPi7 n :: Double
                , let z = abs (x - pi) :: Double]
      ++ linea
     
    linea, cabecera :: String
    linea    = "+------+----------------+----------------+n"
    cabecera = "| n    | Aproximacion   | Error          |n"
  2. enrnarbej
    aproximacionPiNil :: Int -> Double
    aproximacionPiNil n = 3 + 4 * aux [2..] n 1
                        where
                         aux _          0 _ = 0
                         aux (x:y:z:xs) n s = s/(x*y*z) + aux (z:xs) (n-1) (-s)
     
     
    tabla          :: FilePath -> [Int] -> IO ()
    tabla fp xs = do 
            let cabecera = "+------+----------------+----------------+n" ++
                           "| n    | Aproximación   | Error          |n" ++
                           "+------+----------------+----------------+n"
            let datos    = concat [printf "| %4d | %.12f | %.12f |n" n x ap
                         | n <- xs
                         , let x  = aproximacionPiNil n :: Double
                         , let ap = abs (pi-x) :: Double]
            let final    = "+------+----------------+----------------+n"
            writeFile fp (cabecera ++ datos ++ final)
  3. antmorper3
    aproximacionPi :: Int -> Double
    aproximacionPi n = 3 + aux [2..] n 1
     where aux _ 0 _ = 0
           aux (x:y:z:xs) n a = (a*4)/(x*y*z) + aux (z:xs) (n-1) (-a)
     
    errorPi x = abs (pi - aproximacionPi x)
     
    tabla :: FilePath -> [Int] -> IO ()
    tabla f ns = do
      writeFile f (tablaAux ns)
     
    tablaAux :: [Int] -> String
    tablaAux ns =
         linea
      ++ cabecera
      ++ linea
      ++ concat [printf "| %5d | %.12f | %.12f |n" n x y
                | n <- ns
                , let x = aproximacionPi n :: Double
                        ,let y = errorPi n :: Double]
      ++ linea
     
    linea, cabecera :: String
    linea    = "+-------+----------------+----------------+n"
    cabecera = "| n     | Aproximacion   | Error          |n"
  4. antdursan
    aproximacionPi :: Int -> Double
    aproximacionPi x = 3 + sum (take x (zipWith (*) [4/(n*(n+1)*(n+2)) | n <- [2,4..]] sucesion))
     
    sucesion :: [Double]
    sucesion = 1:(-1):sucesion
     
    tabla :: FilePath -> [Int] -> IO ()
    tabla f ns = do
      writeFile f (tablaAux ns)
     
    tablaAux :: [Int] -> String
    tablaAux ns =
         linea
      ++ cabecera
      ++ linea
      ++ concat [printf "| %4d | %.12f | %.12f |n" n x y
                | n <- ns
                , let x = aproximacionPi n :: Double, let y = abs (pi-x)]
      ++ linea
     
    linea, cabecera :: String
    linea    = "+------+----------------+----------------+n"
    cabecera = "| n    | Aproximacion   | Error          |n"
  5. joscasgom1
    aproximacionPi :: Int -> Double
    aproximacionPi n = 3 + sum (aux n)
     
    aux n = zipWith (/) (concat (repeat [4,-4])) [(x^3)-x | x <-take n [3,5..]]
     
     
    linea, cabecera :: String
    linea    = "+----+----------------+------+n"
    cabecera = "| n  | Aproximacion  | Error)|n"
     
    aproximacionAux :: [Int] -> String
    aproximacionAux ns =
         linea
      ++ cabecera
      ++ linea
      ++ concat [printf "| %2d | %.12f |%.12f |n" n x y
                | n <- ns
                , let x = aproximacionPi ( n) :: Double
                , let y = abs( pi - x)]
      ++ linea
     
    tabla          :: FilePath -> [Int] -> IO ()
    tabla f ns = do
      writeFile f (aproximacionAux ns)
  6. Juanjo Ortega (juaorture)
    import Text.Printf
     
    aproximacionPi :: Int -> Double
    aproximacionPi n = 3 + aux 2 3 4
                   where fI = fromIntegral
                         aux x y z | x `div` 2 - 1 == n = 0
                                   | x `mod` 4 == 0     = - 4/fI(x*y*z) + aux z (y+2) (z+2)
                                   | otherwise          =   4/fI(x*y*z) + aux z (y+2) (z+2)
     
    tabla :: FilePath -> [Int] -> IO ()
    tabla f xs = do writeFile f (aux xs)
     
    aux :: [Int] -> String
    aux xs = linea ++
             cabecera ++
             linea ++
             concat [printf "| %4d | %.12f | %.12f |n" n x y
                | n <- xs
                , let x = aproximacionPi n :: Double
                , let y = abs (pi - x) :: Double] ++
             linea
        where linea    = "+------+----------------+----------------+n"
              cabecera = "| n    | Aproximación   | Error          |n"
  7. cescarde
    aproximacionPi4 :: Int -> Double
    aproximacionPi4 n = 3 + sumSerie n
     
    sumSerie :: Int -> Double
    sumSerie n = sum $ take n $ zipWith (*) p q
             where p = cycle [4,-4]
                   q = sucProd (2,3,4)
     
    sucProd :: (Double,Double,Double) -> [Double]
    sucProd p@(a,b,c) = prod p : sucProd (nexts a b c )
            where prod (a,b,c) = 1/(a*b*c)
                  nexts a b c = (a+2,b+2,c+2)
     
    tabla :: FilePath -> [Int] -> IO ()
    tabla f xs = do
      writeFile f (tablaAux xs)
     
    tablaAux :: [Int] -> String
    tablaAux xs =
         linea
      ++ cabecera
      ++ linea
      ++ concat [printf "| %4d | %.16f | %.16f |n" x n z
                | x <- xs
                , let n = aproximacionPi4 x :: Double
                , let z = abs (n-pi) :: Double]
      ++ linea
     
    linea, cabecera :: String
    linea    = "+-------+--------------------+--------------------+n"
    cabecera = "|   n   |    Aproximacion    |       Error        |n"

Escribe tu solución

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