Handle decimal/money arithmetic
machship-mm opened this issue · 2 comments
This library is fantastic!
The one issue I've found is that the Arithmetic is done as floating point numbers (which is fine for that use case) but this falls short when doing math involving decimals.
An example:
func TestDecimalArithmetic(t *testing.T) {
input := ArithmeticVariables{
NumberMap: map[string]float64{
"x": 12.5,
"y": -5,
},
Expression: "(x * 12.146) - y",
}
result, _ := gval.Arithmetic().Evaluate(input.Expression, input.NumberMap)
want := 156.825
if result != want {
t.Errorf("wanted %f; got %f", want, result)
t.FailNow()
}
t.Log(result)
}
This results in this output:
=== RUN TestDecimalArithmetic
arithmetic_test.go:46: wanted 156.825000; got 156.825000
--- FAIL: TestDecimalArithmetic (0.00s)
When inspecting the variable values, I can see that result
has the actual value of 156.82500000000002
.
Do you have any suggestions for what I should do, or is this even a solvable problem?
I was thinking that there could be an EvaluateDecimal
method, which instead of treating numbers as floats, would treat them as a decimal type? For decimals, I use github.com/shopspring/decimal
.
Thanks.
You can Override the == Operator and use a small delta for comparing float64 zu each other. a + delta <= b && a - delta >= b
that should solve your problem.
If you want you can make a push request for func DecimalEqual(delta float64) Language
That could help others, too.
Thanks @generikvault, I've now pushed a pull request that fixes this issue. I've tested it both in the gval repo and in my code base which is using this code and can confirm that this handles decimal arithmetic and logic appropriately.