2014-10-09 48 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