我正在测试一个用Ruby制作的小而简单的库。目标是从EUR
转换为CNY
,反之亦然。简单。
我测试了它以确保一切正常但我遇到了意想不到的问题。当我使用to_euro
后跟to_yuan
时,它应该返回原来的amount
;它没有发生。我尝试.to_f
或round(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结果
我很确定这个问题很常见,有什么想法可以轻松解决吗?
答案 0 :(得分:1)
Float不是一个确切的数字表示,如ruby docs中所述:
Float对象使用本机架构的双精度浮点表示来表示不精确的实数。
这不是ruby错误,因为浮点数只能用固定数量的字节表示,因此无法正确存储十进制数。
或者,您可以使用ruby Rational或BigDecimal
在处理货币和货币转换时使用money gem也相当普遍。