aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--RealCalc.hs33
1 files changed, 26 insertions, 7 deletions
diff --git a/RealCalc.hs b/RealCalc.hs
index ac8ecb5..d54cf84 100644
--- a/RealCalc.hs
+++ b/RealCalc.hs
@@ -22,27 +22,42 @@
module RealCalc (calculate) where
import qualified Expr
+import qualified Data.Ratio
-data Result = RInt Integer | RFloat Double
+data Result = RInt Integer | RFloat Double | RRatio Rational
+
+data ResultPair = RInts Integer Integer | RFloats Double Double | RRatios Rational Rational
instance Show Result where
show (RInt i) = show i
show (RFloat d) = show d
+ show (RRatio r) = show (Data.Ratio.numerator r) ++ "/" ++ show (Data.Ratio.denominator r)
rToDouble :: Result -> Double
rToDouble (RInt i) = fromIntegral i
rToDouble (RFloat d) = d
+rToDouble (RRatio r) = fromIntegral (Data.Ratio.numerator r) / fromIntegral (Data.Ratio.denominator r)
+
+castSame :: Result -> Result -> ResultPair
+castSame a (RFloat b) = RFloats (rToDouble a) b
+castSame (RFloat a) b = RFloats a (rToDouble b)
+castSame (RRatio a) (RRatio b) = RRatios a b
+castSame (RInt a) (RRatio b) = RRatios (fromIntegral a) b
+castSame (RInt a) (RInt b) = RInts a b
+castSame (RRatio a) (RInt b) = RRatios a (fromIntegral b)
genericCombine :: (forall a. Num a => a -> a -> a) -> Result
-> Result -> Result
genericCombine f i j =
- case (i, j) of
- (RInt a, RInt b) -> RInt (f a b)
- _ -> RFloat (f (rToDouble i) (rToDouble j))
+ case castSame i j of
+ RInts a b -> RInt (f a b)
+ RFloats a b -> RFloat (f a b)
+ RRatios a b -> RRatio (f a b)
genericInner :: (forall a. Num a => a -> a) -> Result -> Result
genericInner f (RInt i) = RInt (f i)
genericInner f (RFloat d) = RFloat (f d)
+genericInner f (RRatio r) = RRatio (f r)
simplify :: Expr.Expr -> Result
simplify (Expr.Plus e1 e2) =
@@ -53,13 +68,17 @@ simplify (Expr.Minus e1 e2) =
simplify (Expr.Times e1 e2) =
genericCombine (*) (simplify e1) (simplify e2)
simplify (Expr.Div e1 e2) =
- RFloat (rToDouble (simplify e1) / rToDouble (simplify e2))
+ case castSame (simplify e1) (simplify e2) of
+ RInts a b -> RRatio (a Data.Ratio.% b)
+ RRatios a b -> RRatio (a / b)
+ RFloats a b -> RFloat (a / b)
simplify (Expr.Pow e1 e2) =
case (simplify e1, simplify e2) of
(RInt a, RInt b)
| b >= 0 -> RInt (a ^ b)
- (a, RInt b) -> RFloat (rToDouble a ^^ b)
- (a, RFloat b) -> RFloat (rToDouble a ** b)
+ (RRatio a, RInt b) -> RRatio (a ^^ b)
+ (RFloat a, RInt b) -> RFloat (a ^^ b)
+ (a, b) -> RFloat (rToDouble a ** rToDouble b)
simplify (Expr.EInt i) = RInt i
simplify (Expr.EFloat d) = RFloat d
simplify Expr.E = RFloat (exp 1)