分割后浮点数不相等,然后乘法

时间:2016-08-01 15:16:30

标签: ruby rspec

我正在测试一个用Ruby制作的小而简单的库。目标是从EUR转换为CNY,反之亦然。简单。

我测试了它以确保一切正常但我遇到了意想不到的问题。当我使用to_euro后跟to_yuan时,它应该返回原来的amount;它没有发生。我尝试.to_fround(2) amount变量来修复某些测试,提出新测试,但它永远不会与我期望的全局相同;我没有想法解决这个问题:(

class Currency

  attr_reader :amount, :currency

  def initialize(amount, currency='EUR')
    @amount = amount
    @currency = currency
  end

  def to_yuan
    update_currency!('CNY', amount * Settings.instance.exchange_rate_to_yuan)
  end

  def to_euro
    update_currency!('EUR', amount / Settings.instance.exchange_rate_to_yuan)
  end

  def display
    "%.2f #{current_symbol}" % amount
  end

  private

  def current_symbol
    if currency == 'EUR'
      symbol = Settings.instance.supplier_currency.symbol
    elsif currency == 'CNY'
      symbol = Settings.instance.platform_currency.symbol
    end
  end

  def update_currency!(new_currency, new_amount)
    unless new_currency == currency
      @currency = new_currency
      @amount = new_amount
    end
    self
  end

end

测试

describe Currency do

  let(:rate) { Settings.instance.exchange_rate_to_yuan.to_f }

  context "#to_yuan" do

    it "should return Currency object" do
      expect(Currency.new(20).to_yuan).to be_a(Currency)
    end

    it "should convert to yuan" do
      expect(Currency.new(20).to_yuan.amount).to eql(20.00 * rate)
    end

    it "should convert to euro and back to yuan" do
      # state data test
      currency = Currency.new(150, 'CNY')
      expect(currency.to_euro).to be_a(Currency)
      expect(currency.to_yuan).to be_a(Currency)
      expect(currency.amount).to eql(150.00)
    end

  end

  context "#to_euro" do

    it "should convert to euro" do
      expect(Currency.new(150, 'CNY').to_euro.amount).to eql(150 / rate)
    end

  end

  context "#display" do

    it "should display euros" do
      expect(Currency.new(10, 'EUR').display).to eql("10.00 €")
    end

    it "should display yuan" do
      expect(Currency.new(60.50, 'CNY').display).to eql("60.50 ¥")
    end

  end


end

这是我的RSpec结果

enter image description here

我很确定这个问题很常见,有什么想法可以轻松解决吗?

1 个答案:

答案 0 :(得分:1)

Float不是一个确切的数字表示,如ruby docs中所述:

  

Float对象使用本机架构的双精度浮点表示来表示不精确的实数。

这不是ruby错误,因为浮点数只能用固定数量的字节表示,因此无法正确存储十进制数。

或者,您可以使用ruby RationalBigDecimal

在处理货币和货币转换时使用money gem也相当普遍。