I'm using Rails with the money-rails gem to handle money columns.
Is there any way to prevent floating point errors from occuring? (even a hack will do, I just want to make sure no such errors are presented to the end user)
Rspec example case:
it "correctly manipulates simple money calculations" do
# Money.infinite_precision = false or true i've tried both
start_val = Money.new("1000", "EUR")
expect(start_val / 30 * 30).to eq start_val
end
Result
Failure/Error: expect(start_val / 30 * 30).to eq start_val
expected: #<Money fractional:1000.0 currency:EUR>
got: #<Money fractional:999.99999999999999999 currency:EUR>
(compared using ==)
Diff:
@@ -1,2 +1,2 @@
-#<Money fractional:1000.0 currency:EUR>
+#<Money fractional:999.99999999999999999 currency:EUR>
You should use decimals for money amounts. See http://ruby-doc.org/stdlib-2.1.1/libdoc/bigdecimal/rdoc/BigDecimal.html for instance. It has arbitrary precision arithmetic.
EDIT: In your case you should probably change your Rspec to something like:
it "correctly manipulates simple money calculations" do
# Money.infinite_precision = false or true i've tried both
start_val = Money.new("1000", "EUR")
thirty = BigDecimal.new("30")
expect(start_val / thirty * thirty).to eq start_val
end
EDIT2: in this very case 1000/30 cannot be represented as a finite decimal number. You have to either use Rational
class or do rounding. Example code:
it "correctly manipulates simple money calculations" do
# Money.infinite_precision = false or true i've tried both
start_val = Money.new("1000", "EUR")
expect(start_val.amount.to_r / 30.to_r * 30.to_r).to eq start_val.amount.to_r
end