Closed avibryant closed 4 years ago
cc @sritchie
The motivation for using BigDecimal
is to ensure that constants which simplify to small integers mathematically, and which end up as coefficients or exponents, will also simplify to small integers numerically.
A contrived example might be:
(x + 0.1)(2x + 0.1) - (3x/10)
= 3x^2 + 0.2x + 0.1x +0.01 - 0.3x
= 3x^2 + 0.01
However, with floating point math, you end up with a (5.55e-17 x) term in there you don't want.
I bet it would be good enough to implement a simple case class Fraction(numerator: Int, denominator: Int)
, and two different constant Real
types, one with double and one with fraction, and then stay in fraction-space as long as possible but convert to double whenever necessary.
A weird idea that would be interesting to play with is: what about a single representation which is (numerator: Double, denominator: Int)
? The intuition here is just that the problems tend to come from adjusting the order of magnitude down and then up again (eg dividing by 10 and then later multiplying by 10), and so if we can isolate the double values somewhat from these shifts, we should avoid a lot of the problems.
BigDecimal causes performance problems, especially in the forward simulation phase. We may be able to get clever about a mixture of
Double
andInt
representations that gives us the best of both worlds.