squants
squants copied to clipboard
Loss of precision when dividing Quantity
When you deal with money, there is a method
def /(that: BigDecimal): Money = new Money(amount / that)(currency)
that allows you to divide money by an arbitrarily large BigDecimal without losing precision.
There is no such method on regular Quantity types:
e.g.
Grams(5.1) / BigDecimal(1000)
// cannot be applied to (scala.math.BigDecimal)
// Grams(5.1) / BigDecimal(1000)
As such it appears to be impossible to divide Quantity types without potentially losing precision.
Even using the divide method produces a loss of precision:
Grams(5.1).divide(1000)
// squants.mass.Mass = 0.0050999999999999995 g
divideAndRemainder appears to handle the precision correctly but is a tedious interface for a simple division:
Grams(5.1).divideAndRemainder(1000)
// (squants.mass.Mass, squants.mass.Mass) = (0.0 g,5.1 g)
The only way I can see to actually produce the correct result currently is with the following approach:
Grams(5.1).map(x => (x / BigDecimal(1000)).toDouble)
// squants.mass.Mass = 0.0051 g
Perhaps this method could be added to Quantity?
def /(that: BigDecimal): A = this.map(v => (v / that).toDecimal)
Happy to raise a pull request if this solution makes sense!
Similar to #253 this is a known issue b/c the library currently uses doubles. For 2.x, this will be fixed.
@camjo The map method is the best choice for overcoming these types of limitations. I do agree with @derekmorr that making the underlying value generic instead of Double will go a great way toward improving the precision of the library.
In the meantime, I do think your proposed method would be a worthy addition.