如何防止Ruby Money浮点错误 [英] How to prevent Ruby money floating point errors

查看:114
本文介绍了如何防止Ruby Money浮点错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将Rails与money-rails gem配合使用来处理钱栏.

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示例案例:

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

结果

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>

推荐答案

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

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.

在您的情况下,您可能应该将Rspec更改为以下内容:

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

在这种情况下,不能将1000/30表示为有限的十进制数.您必须使用Rational类或进行舍入.示例代码:

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

这篇关于如何防止Ruby Money浮点错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆