2014-10-09 47 views
5
-:total_cost_with_tax => #<BigDecimal:7fda9d17aaf0,'0.105225E4',18(45)>, 
-:total_cost_without_tax => #<BigDecimal:7fda9d17b450,'0.972E3',9(36)>, 
-:total_last_installment_amount => #<BigDecimal:7fda9d17b978,'0.8011E2',18(45)>, 
-:total_monthly_installment_amount => #<BigDecimal:7fda9d17abb8,'0.8011E2',18(45)>, 
-:total_tax => #<BigDecimal:7fda9d17b068,'0.8025E2',18(45)>, 

+:total_cost_with_tax => #<BigDecimal:7fda9d0184c8,'0.105225E4',18(36)>, 
+:total_cost_without_tax => #<BigDecimal:7fda91ff2b48,'0.972E3',9(27)>, 
+:total_last_installment_amount => #<BigDecimal:7fda91fee548,'0.8011E2',18(36)>, 
+:total_monthly_installment_amount => #<BigDecimal:7fda91fe72c0,'0.8011E2',18(36)>, 
+:total_tax => #<BigDecimal:7fda9d00a2b0,'0.8025E2',18(36)>, 

因此,这些都是散布在我的一些测试... rspec 2,rails 3.我使用.should eq()来比较散列来比较。我似乎无法得到正确的咒语。看起来这是一件精确的事情,看起来很愚蠢。rspec大十进制匹配器

回答

6

RSpec的3有BigDecimal的EQ:

x.should eq(y) 

expect(x).to eq(y) 

如果你比较将BigDecimal的浮动,要注意的精度影响比较。

您可以使用此:

x.should be_within(delta).of(y) 

expect x.to be_within(delta).of(y) 

如果你比较具有不同精度度的两个BigDecimal数字,要知道,这些数字可以从hash根据您的平台,什么上显示来自inspect不同的结果,也您正在运行的Ruby BigDecimal版本。

例如,这可能发生:

BigDecimal.new("2").hash == BigDecimal.new("2.0").hash 
=> false 

你的输出显示您的BigDecimal的字符串表示略有不同。

这里就是你的字符串的意思是:

  • 第1部分是对象的地址。
  • 第2部分是以字符串表示的数值。
  • 第3部分是有效位数,然后是最大有效位数。

你的输出显示您的串具有不同的目的地址中,相同的数值(即第2部分)中,相同的数字显著(部分3中的第一个数字),但不同数字的最大位数显著。你可以使用rspec be_within匹配器来解决你的问题。

注意,红宝石BigDecimal号码和Float个数都为浮点数:

  • BigDecimal是一个任意精度小数浮点数。

  • A Float是原生架构的双精度二进制浮点数。

您可以通过这样看BigDecimal十进制浮点表示:

require 'bigdecimal' 
x=BigDecimal.new(100) 
=> #<BigDecimal:7f8e62038570,'0.1E3',9(27)> 

的尾数部分是“0.1”和指数部分是“E3”。

请注意,这是典型的Ruby MRI/KRI虚拟机。其他Ruby虚拟机(如JRuby)的实现可能会有所不同,因为Java有自己的bignum代码。

当您比较两种不同类型的浮点数(如BigDecimal和Float)时,您可能会得到看起来与直觉不符的结果,因为这些类型使用不同的基数(小数对二进制),不同的精度和不同的精度Ruby类。

例子:

BigDecimal.new("1.111111111111111") === 1.111111111111111 
=> true 
BigDecimal.new("1.1111111111111111") === 1.1111111111111111 
=> false 
+0

为了记录在案:不正确的。 usijng BigDecimal的全部意义在于它不会像Float那样行事;你应该得到你输入的号码。 – 2016-01-15 14:42:39

+0

@Andy我添加了更多的细节来解决你的评论。 – joelparkerhenderson 2016-01-15 22:48:20

+0

非常好,但我的评论的观点是,你不应该*需要*使用'be_within'来匹配一个BegDecimal。这不像一个浮动;由于数字的存储方式,您无需考虑舍入错误。 – 2016-01-18 08:58:12

2

使用RSpec 3.x中,你可以使用的BigDecimal的eq匹配像你可以使用它的浮动。

RSpec.describe "an integer" do 
    it "is equal to a float of the same value" do 
    expect(5).to eq(5.0) 
    end 
end 

欲了解更多信息,请参阅RSpec的文档: https://www.relishapp.com/rspec/rspec-expectations/v/3-4/docs/built-in-matchers/equality-matchers

+0

恕我直言,这比公认的解决方案更好 – damoiser 2015-12-09 09:52:47

+1

@damoiser当RSpec是版本2而不是版本3时,系统询问了问题。现在我会更新我的答案,因为我同意你的看法。 – joelparkerhenderson 2016-01-15 23:02:29