module ComputableReals where import Data.Ratio type Nat = Integer type Bounds = (Rational, Rational) newtype CReal = CReal { bounds :: Nat -> Bounds } instance Num CReal where (+) = plusX (-) = minusX (*) = timesX negate = negX abs = error "no abs" signum = error "no signum" fromInteger = fromRatX . fromInteger instance Fractional CReal where (/) = error "no div" recip = error "no recip" fromRational = fromRatX lbound, ubound :: CReal -> Nat -> Rational lbound x n = fst $ bounds x n ubound x n = snd $ bounds x n fromRatX :: Rational -> CReal fromRatX r = CReal $ const (r, r) negX :: CReal -> CReal negX x = CReal $ \n -> (negate $ ubound x n, negate $ lbound x n) plusX, minusX, timesX :: CReal -> CReal -> CReal plusX x y = CReal h where h n = (lb, ub) where lb = (lbound x n) + (lbound y n) ub = (ubound x n) + (ubound y n) minusX x y = plusX x (negX y) timesX x y = CReal h where h n = (lb, ub) where (xl, xu) = bounds x n (yl, yu) = bounds y n values = [xl * yl, xl * yu, xu * yl, xu * yu] lb = minimum values ub = maximum values floorX :: CReal -> Integer floorX x = startWith 0 where startWith n | lfloor == ufloor = lfloor | otherwise = startWith (n + 1) where lfloor = floor $ lbound x n ufloor = floor $ ubound x n eX = CReal h where h n = (lb, ub) where n' = n + 1 lb = sum [ 1 % product [1..i] | i <- [0..n'] ] ub = lb + 1 % (n' * product [1..n']) test :: [Integer] test = [floorX (100500 * eX), floor (100500 * exp 0)] -- наше и стандартное main :: IO [Integer] main = return test