Aproximación del número e
El número e se define como el límite de la sucesión .
Definir las funciones
1 2 |
aproxE :: Int -> [Double] errorAproxE :: Double -> Int |
tales que
aproxE k
es la lista de losk
primeros términos de la sucesión. Por ejemplo,
1 2 |
aproxE 4 == [2.0,2.25,2.37037037037037,2.44140625] last (aproxE (7*10^7)) == 2.7182818287372563 |
errorE x
es el menor número de términos de la sucesión necesarios para obtener su límite con un error menor quex
. Por ejemplo,
1 2 3 |
errorAproxE 0.1 == 13 errorAproxE 0.01 == 135 errorAproxE 0.001 == 1359 |
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
import Test.QuickCheck -- 1ª definición de aproxE -- ======================= aproxE1 :: Int -> [Double] aproxE1 k = [(1+1/n)**n | n <- [1..k']] where k' = fromIntegral k -- 2ª definición de aproxE -- ======================= aproxE2 :: Int -> [Double] aproxE2 0 = [] aproxE2 n = aproxE2 (n-1) ++ [(1+1/n')**n'] where n' = fromIntegral n -- 3ª definición de aproxE -- ======================= aproxE3 :: Int -> [Double] aproxE3 = reverse . aux . fromIntegral where aux 0 = [] aux n = (1+1/n)**n : aux (n-1) -- 4ª definición de aproxE -- ======================= aproxE4 :: Int -> [Double] aproxE4 k = aux [] (fromIntegral k) where aux xs 0 = xs aux xs n = aux ((1+1/n)**n : xs) (n-1) -- 5ª definición de aproxE -- ======================= aproxE5 :: Int -> [Double] aproxE5 k = map (\ n -> (1+1/n)**n) [1..k'] where k' = fromIntegral k -- Comprobación de equivalencia de aproxE -- ====================================== -- La propiedad es prop_aproxE :: Positive Int -> Bool prop_aproxE (Positive k) = all (== aproxE1 k) [aproxE2 k, aproxE3 k, aproxE4 k, aproxE5 k] -- La comprobación es -- λ> quickCheck prop_aproxE -- +++ OK, passed 100 tests. -- Comparación de eficiencia de aproxE -- =================================== -- La comparación es -- λ> last (aproxE1 (2*10^4)) -- 2.718213874533619 -- (0.04 secs, 5,368,968 bytes) -- λ> last (aproxE2 (2*10^4)) -- 2.718213874533619 -- (5.93 secs, 17,514,767,104 bytes) -- λ> last (aproxE3 (2*10^4)) -- 2.718213874533619 -- (0.05 secs, 9,529,336 bytes) -- λ> last (aproxE4 (2*10^4)) -- 2.718213874533619 -- (0.05 secs, 9,529,184 bytes) -- λ> last (aproxE5 (2*10^4)) -- 2.718213874533619 -- (0.01 secs, 4,888,960 bytes) -- -- λ> last (aproxE1 (2*10^6)) -- 2.7182811492688552 -- (0.54 secs, 480,570,120 bytes) -- λ> last (aproxE3 (2*10^6)) -- 2.7182811492688552 -- (2.07 secs, 896,570,280 bytes) -- λ> last (aproxE4 (2*10^6)) -- 2.7182811492688552 -- (2.18 secs, 896,570,336 bytes) -- λ> last (aproxE5 (2*10^6)) -- 2.7182811492688552 -- (0.09 secs, 432,570,112 bytes) -- 1ª definición de errorAproxE -- ============================ errorAproxE1 :: Double -> Int errorAproxE1 x = round (head [n | n <- [1..], abs (exp 1 - (1+1/n)**n) < x]) -- 2ª definición de errorAproxE -- ============================ errorAproxE2 :: Double -> Int errorAproxE2 x = aux 1 where aux n | abs (exp 1 - (1+1/n)**n) < x = round n | otherwise = aux (n+1) -- 3ª definición de errorAproxE -- ============================ errorAproxE3 :: Double -> Int errorAproxE3 x = round (head (dropWhile (\ n -> abs (exp 1 - (1+1/n)**n) >= x) [1..])) -- Comprobación de equivalencia de errorAproxE -- =========================================== -- La propiedad es prop_errorAproxE :: Positive Double -> Bool prop_errorAproxE (Positive x) = all (== errorAproxE1 x) [errorAproxE2 x, errorAproxE3 x] -- La comprobación es -- λ> quickCheck prop_errorAproxE -- +++ OK, passed 100 tests. -- Comparación de eficiencia de errorAproxE -- ======================================== -- La comparación es -- λ> errorAproxE1 0.000001 -- 1358611 -- (1.70 secs, 674,424,552 bytes) -- λ> errorAproxE2 0.000001 -- 1358611 -- (1.79 secs, 739,637,704 bytes) -- λ> errorAproxE3 0.000001 -- 1358611 -- (1.20 secs, 609,211,144 bytes) |
El código se encuentra en GitHub.
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
from itertools import dropwhile, islice from math import e from sys import setrecursionlimit from timeit import Timer, default_timer from typing import Iterator from hypothesis import given from hypothesis import strategies as st setrecursionlimit(10**6) # 1ª definición de aproxE # ======================= def aproxE1(k: int) -> list[float]: return [(1 + 1/n)**n for n in range(1, k + 1)] # 2ª definición de aproxE # ======================= def aproxE2(n: int) -> list[float]: if n == 0: return [] return aproxE2(n - 1) + [(1 + 1/n)**n] # 3ª definición de aproxE # ======================= def aproxE3(n: int) -> list[float]: def aux(n: int) -> list[float]: if n == 0: return [] return [(1 + 1/n)**n] + aux(n - 1) return list(reversed(aux(n))) # 4ª definición de aproxE # ======================= def aproxE4(n: int) -> list[float]: def aux(xs: list[float], n: int) -> list[float]: if n == 0: return xs return aux([(1 + 1/n)**n] + xs, n - 1) return aux([], n) # 5ª definición de aproxE # ======================= def aproxE5(n: int) -> list[float]: return list(map((lambda k: (1+1/k)**k), range(1, n+1))) # 6ª definición de aproxE # ======================= def aproxE6(n: int) -> list[float]: r = [] for k in range(1, n+1): r.append((1+1/k)**k) return r # Comprobación de equivalencia de aproxE # ====================================== # La propiedad es @given(st.integers(min_value=1, max_value=100)) def test_aproxE(n: int) -> None: r = aproxE1(n) assert aproxE2(n) == r assert aproxE3(n) == r assert aproxE4(n) == r assert aproxE5(n) == r assert aproxE6(n) == r # La comprobación es # src> poetry run pytest -q aproximacion_del_numero_e.py # 1 passed in 0.60s # Comparación de eficiencia de aproxE # =================================== def tiempo(ex: str) -> None: """Tiempo (en segundos) de evaluar la expresión e.""" t = Timer(ex, "", default_timer, globals()).timeit(1) print(f"{t:0.2f} segundos") # La comparación es # >>> tiempo('aproxE1(20000)') # 0.00 segundos # >>> tiempo('aproxE2(20000)') # 0.43 segundos # >>> tiempo('aproxE3(20000)') # 0.60 segundos # >>> tiempo('aproxE4(20000)') # 1.23 segundos # >>> tiempo('aproxE5(20000)') # 0.00 segundos # >>> tiempo('aproxE6(20000)') # 0.00 segundos # >>> tiempo('aproxE1(10**7)') # 1.18 segundos # >>> tiempo('aproxE5(10**7)') # 1.48 segundos # >>> tiempo('aproxE6(10**7)') # 1.43 segundos # 1ª definición de errorAproxE # ============================ # naturales es el generador de los números naturales positivos, Por # ejemplo, # >>> list(islice(naturales(), 5)) # [1, 2, 3, 4, 5] def naturales() -> Iterator[int]: i = 1 while True: yield i i += 1 def errorAproxE1(x: float) -> int: return list(islice((n for n in naturales() if abs(e - (1 + 1/n)**n) < x), 1))[0] # # 2ª definición de errorAproxE # # ============================ def errorAproxE2(x: float) -> int: def aux(n: int) -> int: if abs(e - (1 + 1/n)**n) < x: return n return aux(n + 1) return aux(1) # 3ª definición de errorAproxE # ============================ def errorAproxE3(x: float) -> int: return list(islice(dropwhile(lambda n: abs(e - (1 + 1/n)**n) >= x, naturales()), 1))[0] # Comprobación de equivalencia de errorAproxE # =========================================== @given(st.integers(min_value=1, max_value=100)) def test_errorAproxE(n: int) -> None: r = errorAproxE1(n) assert errorAproxE2(n) == r assert errorAproxE3(n) == r # La comprobación es # src> poetry run pytest -q aproximacion_del_numero_e.py # 2 passed in 0.60s # Comparación de eficiencia de aproxE # =================================== # La comparación es # >>> tiempo('errorAproxE1(0.0001)') # 0.00 segundos # >>> tiempo('errorAproxE2(0.0001)') # 0.00 segundos # >>> tiempo('errorAproxE3(0.0001)') # 0.00 segundos # # >>> tiempo('errorAproxE1(0.0000001)') # 2.48 segundos # >>> tiempo('errorAproxE3(0.0000001)') # 2.61 segundos |
El código se encuentra en GitHub.