Una serie infinita para el cálculo de pi, publicada por Nilakantha en el siglo XV, es
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" |