2014-10-09 2 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, рельсы 3. Я сравнение хэш с помощью .should eq() для сравнения. Кажется, я не могу получить заклинание. Похоже, это точная вещь, которая кажется глупой.RSpec большой десятичная согласовань

ответ

6

RSpec 3 имеет BigDecimal эк:

x.should eq(y) 

expect(x).to eq(y) 

Если вы сравниваете BigDecimal в Float, быть в курсе точность может повлиять на сравнение.

Вы можете использовать это:

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

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

Если вы сравниваете два числа BigDecimal, которые имеют разные Precisions, следует помнить, что эти цифры могут показать результаты, отличные от inspect, а также от hash в зависимости от вашей платформы и что версию Ruby BigDecimal, которую вы запускаете.

Например, это может произойти:

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

Ваш вывод показывает, что ваши BigDecimal строковые представления немного отличаются.

Вот что означают ваши строки:

  • Часть 1 является адрес объекта.
  • Часть 2 - это числовое значение, представленное в виде строки.
  • Часть 3 - это количество значащих цифр, а затем максимальное количество значащих цифр.

Ваш вывод показывает, что ваши строки имеют разные адреса объектов, одинаковые значения числа (т. Е. Часть 2), одинаковые значащие цифры (первое число в части 3), но разные числа максимальных значащих цифр.

На ваш вопрос, используя RSpec 2 и сравнивая хеши BigDecimal, вы можете решить вашу проблему, используя сопряжение 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 VM.Реализации могут отличаться от других Ruby VM, таких как JRuby, потому что Java имеет свой собственный код bignum.

При сравнении двух разных типов чисел с плавающей запятой, таких как BigDecimal и Float, вы можете получить результаты, которые могут показаться противоречивыми, поскольку типы используют разные базы (десятичные или двоичные), различные префиксы и разные Рубиновые классы.

Пример:

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

Для записи: не правда. Весь смысл usigng BigDecimal в том, что он не * ведет себя как Float; вы должны получить номер, который вы положили. –

+0

@ Энди Я добавил больше подробностей, чтобы ответить на ваш комментарий. – joelparkerhenderson

+0

отлично, но точка моего комментария заключалась в том, что вам не нужно * использовать * be_within' для соответствия BegDecimal. Это не похоже на Float; вам не нужно учитывать ошибку округления из-за способа сохранения номера. –

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

+1

@damoiser Вопрос был задан, когда RSpec была версией 2, а не версией 3. Я сейчас обновлю свой ответ, чтобы показать, потому что я согласен с вами. – joelparkerhenderson

Смежные вопросы