Ir al contenido principal

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 la función

suelo :: Float -> Integer

tal que (suelo x) es el suelo de x. Por ejemplo,

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

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
--    λ> quickCheck prop_suelo
--    +++ OK, passed 100 tests.