La serie 1 – 2 + 3 – 4 + ···
En este ejercicio se considerará la serie
1 |
1 - 2 + 3 - 4 + 5 - 6 + 7 - 8 + 9 - 10 + ··· |
Definir las funciones
1 2 |
serie :: [Integer] sumaSerie :: Integer -> Integer |
tales que
- serie es lalista de los términos de la serie anterior; es decir,
1 |
take 7 serie == [1,-2,3,-4,5,-6,7] |
- (sumaSerie n) es la suma de los n primeros términos de la serie. Por ejemplo,
1 2 3 4 |
sumaSerie 5 == 3 sumaSerie 6 == -3 sumaSerie 2021 == 1011 length (show (sumaSerie (10^1000))) == 1001 |
Comprobar con QuickCheck que
- la suma de la serie se puede hacer tan grande como se desee; es decir, que para todo número a existe un n tal que la suma de los n primeros términos de la serie es mayor que a;
- la suma de la serie se puede hacer tan pequeña como se desee; es decir, que para todo número a existe un n tal que la suma de los n primeros términos de la serie es menor que a.
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 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 |
import Data.List (cycle, genericTake) import Test.QuickCheck (Property, (==>), quickCheck) -- 1ª definición de serie -- ====================== serie :: [Integer] serie = [(-1)^(n-1) * n | n <- [1..]] -- 2ª definición de serie -- ====================== serie2 :: [Integer] serie2 = zipWith (*) (cycle [1,-1]) [1..] -- 3ª definición de serie -- ====================== serie3 :: [Integer] serie3 = zipWith ($) (cycle [id,negate]) [1..] -- 1ª definición de sumaSerie -- ========================== sumaSerie :: Integer -> Integer sumaSerie n = sum (genericTake n serie) -- 2ª definición sumaSerie -- ======================= -- La 2ª definición se basa en la siguiente observación -- + Si n es par, entonces -- 1 - 2 + 3 - 4 + 5 - 6 + ··· + (n-1) - n -- = (1 - 2) + (3 - 4) + (5 - 6) + ··· + ((n-1) - n) -- = -1 - 1 - 1 - ··· - 1 -- = -1 * n/2 -- + Si n es impar, entonces -- 1 - 2 + 3 - 4 + 5 - 6 + ··· + (n-2) - (n-1) + n -- = (1 - 2) + (3 - 4) + (5 - 6) + ··· + ((n-2) - (n-1)) + n -- = -1 - 1 - 1 - ··· - 1 + n -- = -1 * (n-1)/2 + n -- = n - ((n-1)/2) sumaSerie2 :: Integer -> Integer sumaSerie2 n | even n = -(n `div` 2) | otherwise = n - ((n - 1) `div` 2) -- 3ª definición sumaSerie -- ======================= -- La 3ª definición se basa en la siguiente observación -- λ> [sumaSerie n | n <- [1..20]] -- [1,-1,2,-2,3,-3,4,-4,5,-5,6,-6,7,-7,8,-8,9,-9,10,-10] sumaSerie3 :: Integer -> Integer sumaSerie3 n = ((-1)^(n-1)*(2*n+1)+1) `div` 4 -- Equivalencia -- ============ -- La propiedad es prop_sumaSerie_equiv :: Integer -> Property prop_sumaSerie_equiv n = n > 0 ==> sumaSerie n == sumaSerie2 n && sumaSerie2 n == sumaSerie3 n -- La comprobación es -- λ> quickCheck prop_sumaSerie_equiv -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> sumaSerie (10^6) -- -500000 -- (3.34 secs, 5,106,633,208 bytes) -- λ> sumaSerie2 (10^6) -- -500000 -- (0.01 secs, 102,600 bytes) -- λ> sumaSerie3 (10^6) -- -500000 -- (0.02 secs, 110,976 bytes) -- λ> sumaSerie3 (10^6) -- -500000 -- Propiedad -- ========= -- La propiedad es prop_sumaSerie :: Integer -> Bool prop_sumaSerie a = any (> a) sumas && any (< a) sumas where sumas = [sumaSerie2 n | n <- [1..]] -- La comprobación es -- λ> quickCheck prop_sumaSerie -- +++ OK, passed 100 tests. |