La función suelo
La función suelo asigna a cada número real el número entero más próximo por defecto; es decir, el mayor número entero igual o menor que ese número real. Por ejemplo, al -2.4 le asigna el -3 y al 1.7 el 1.
Haskell tiene una implementación de la función suelo llamada floor. El objetivo de este ejercicio es redefinir dicha función; es decir, definir (sin usar floor, round ni ceiling) la función
1 |
suelo :: Float -> Integer |
tal que (suelo x) es el suelo de x. Por ejemplo,
1 2 3 4 5 6 7 |
suelo (-2.7) == -3 suelo (-2.4) == -3 suelo (-2) == -2 suelo 0 == 0 suelo 2 == 2 suelo 2.4 == 2 suelo 2.7 == 2 |
Comprobar con QuickCheck que las funciones suelo y floor son equivalentes.
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 |
import Test.QuickCheck -- 1ª definición (por comprensión) -- =============================== suelo1 :: Float -> Integer suelo1 x | x < 0 = head [m | m <- [-1,-2..], fromIntegral m <= x] | otherwise = head [m | m <- [1..], x < fromIntegral m] - 1 -- 2ª definición (con until) -- ========================= suelo2 :: Float -> Integer suelo2 x | x < 0 = until (`menorI` x) (subtract 1) (-1) | otherwise = until (x `menor`) (+1) 1 - 1 where menorI m x = fromIntegral m <= x menor x m = x < fromIntegral m -- 3ª definición (con until sin auxiliares): suelo3 :: Float -> Integer suelo3 x | x < 0 = until ((<=x) . fromIntegral) (subtract 1) (-1) | otherwise = until ((x<) . fromIntegral) (+1) 1 - 1 -- 4ª definición (con show, read y takeWhile): suelo4 :: Float -> Integer suelo4 x | r < 0 = n-1 | otherwise = n where n = read (takeWhile (/='.') (show x)) r = x - fromIntegral n -- 5ª definición (con properFraction): suelo5 :: Float -> Integer suelo5 x = if r < 0 then n-1 else n where (n,r) = properFraction x -- 6ª definición (por búsqueda binaria): suelo6 :: Float -> Integer suelo6 x = fst (until unitario (mejora x) (acota x)) where inferior x = until (`menorI` x) (*2) (-1) superior x = until (x `menor`) (*2) 1 menorI m x = fromIntegral m <= x menor x m = x < fromIntegral m acota x = (inferior x, superior x) mejora x (m,n) = if p `menorI` x then (p,n) else (m,p) where p =(m+n) `div` 2 unitario (m,n) = (m+1 == n) -- La propiedad es prop_suelo x = suelo1 x == y && suelo2 x == y && suelo3 x == y && suelo4 x == y && suelo5 x == y && suelo6 x == y where y = floor x -- La comprobación es -- ghci> quickCheck prop_suelo -- +++ OK, passed 100 tests. |
Eliminando un caso innecesario: