3

我将 Rails 与 money-rails gem 一起使用来处理货币列。

有什么方法可以防止浮点错误的发生?(即使是黑客也可以,我只是想确保不会向最终用户显示此类错误)

Rspec 示例案例:

  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

结果

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>
4

1 回答 1

6

您应该使用小数来表示金额。例如,参见http://ruby-doc.org/stdlib-2.1.1/libdoc/bigdecimal/rdoc/BigDecimal.html。它具有任意精度的算术。

编辑:在您的情况下,您可能应该将您的 Rspec 更改为:

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:在这种情况下,1000/30 不能表示为有限十进制数。您必须使用Rational类或进行舍入。示例代码:

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
于 2015-08-25T10:49:49.977 回答