Cálculo de pi usando el producto de Wallis
El producto de Wallis es una expresión, descubierta por John Wallis en 1655, para representar el valor de π y que establece que:
1 2 3 |
π 2 2 4 4 6 6 8 8 --- = --- · --- · --- · --- · --- · --- · --- · --- ··· 2 1 3 3 5 5 7 7 9 |
Definir las funciones
1 2 3 4 |
factoresWallis :: [Rational] productosWallis :: [Rational] aproximacionPi :: Int -> Double errorPi :: Double -> Int |
tales que
- factoresWallis es la sucesión de los factores del productos de Wallis. Por ejemplo,
1 2 |
λ> take 10 factoresWallis [2 % 1,2 % 3,4 % 3,4 % 5,6 % 5,6 % 7,8 % 7,8 % 9,10 % 9,10 % 11] |
- productosWallis es la sucesión de los productos de los primeros factores de Wallis. Por ejemplo,
1 2 |
λ> take 7 productosWallis [2 % 1,4 % 3,16 % 9,64 % 45,128 % 75,256 % 175,2048 % 1225] |
- (aproximacionPi n) es la aproximación de pi obtenida multiplicando los n primeros factores de Wallis. Por ejemplo,
1 2 3 4 |
aproximacionPi 20 == 3.2137849402931895 aproximacionPi 200 == 3.1493784731686008 aproximacionPi 2000 == 3.142377365093878 aproximacionPi 20000 == 3.141671186534396 |
- (errorPi x) es el menor número de factores de Wallis necesarios para obtener pi con un error menor que x. Por ejemplo,
1 2 3 4 |
errorPi 0.1 == 14 errorPi 0.01 == 155 errorPi 0.001 == 1569 errorPi 0.0001 == 15707 |
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 44 45 46 47 48 49 50 51 52 |
import Data.Ratio factoresWallis :: [Rational] factoresWallis = concat [[y%(y-1), y%(y+1)] | x <- [1..], let y = 2*x] productosWallis :: [Rational] productosWallis = scanl1 (*) factoresWallis aproximacionPi :: Int -> Double aproximacionPi n = fromRational (2 * productosWallis !! n) errorPi :: Double -> Int errorPi x = head [n | n <- [1..] , abs (pi - aproximacionPi n) < x] -- 2ª definición de errorPi errorPi2 :: Double -> Int errorPi2 x = length (takeWhile (>=x) [abs (pi - 2 * fromRational y) | y <- productosWallis]) -- 2ª definición de aproximacionPi aproximacionPi2 :: Int -> Double aproximacionPi2 n = 2 * productosWallis2 !! n productosWallis2 :: [Double] productosWallis2 = scanl1 (*) factoresWallis2 factoresWallis2 :: [Double] factoresWallis2 = concat [[y/(y-1), y/(y+1)] | x <- [1..], let y = 2*x] -- 3ª definición de errorPi errorPi3 :: Double -> Int errorPi3 x = head [n | n <- [1..] , abs (pi - aproximacionPi2 n) < x] -- Comparación de eficiencia -- λ> errorPi 0.001 -- 1569 -- (0.82 secs, 374,495,816 bytes) -- -- λ> errorPi2 0.001 -- 1569 -- (0.79 secs, 369,282,320 bytes) -- -- λ> errorPi3 0.001 -- 1569 -- (0.04 secs, 0 bytes) |
5 Comentarios