除法和乘法后浮点数不相等

编程入门 行业动态 更新时间:2024-10-24 04:35:04
本文介绍了除法和乘法后浮点数不相等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

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

我对其进行了测试以确保一切正常,但出现了意外问题.当我使用 to_euro 后跟 to_yuan 时,它应该回到原来的 amount ;它不会发生.我尝试 .to_f 或 round(2) 修复一些测试的 amount 变量,提出新的测试,但它永远不等于我全球范围内期待;我已经没有办法解决这个问题了:(

class 货币attr_reader :金额,:货币def 初始化(金额,货币 =欧元")@金额=金额@currency = 货币结尾def to_yuanupdate_currency!('CNY', amount * Settings.instance.exchange_rate_to_yuan)结尾def to_euroupdate_currency!('EUR', 金额/Settings.instance.exchange_rate_to_yuan)结尾定义显示"%.2f #{current_symbol}" % 数量结尾私人的def current_symbol如果货币 == '欧元'符号 = Settings.instance.supplier_currency.symbolelsif 货币 == 'CNY'符号 = Settings.instance.platform_currency.symbol结尾结尾def update_currency!(new_currency, new_amount)除非新货币 == 货币@currency = new_currency@amount = new_amount结尾自己结尾结尾

测试

describe Currency dolet(:rate) { Settings.instance.exchange_rate_to_yuan.to_f }上下文#to_yuan"做它应该返回货币对象"做期望(货币.新(20).to_yuan).to be_a(货币)结尾它应该转换成人民币"吗期望(Currency.new(20).to_yuan.amount).to eql(20.00 * rate)结尾它应该转换成欧元再转换成人民币"做# 状态数据测试货币 = Currency.new(150, 'CNY')期望(货币.to_euro).to be_a(货币)期望(货币.to_yuan).to be_a(货币)期望(货币.金额).到 eql(150.00)结尾结尾上下文#to_euro"做它应该转换为欧元"做期望(Currency.new(150,'CNY').to_euro.amount).to eql(150/rate)结尾结尾上下文#display"做它应该显示欧元"做期望(Currency.new(10,'EUR').显示).to eql(10.00€")结尾它应该显示元"做expect(Currency.new(60.50, 'CNY').display).to eql("60.50 ¥")结尾结尾结尾

这是我的 RSpec 结果

我很确定这个问题很常见,知道如何轻松解决吗?

解决方案

Float 不是精确的数字表示,如 ruby 文档:

Float 对象使用原生架构的双精度浮点表示法来表示不精确的实数.

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

或者,您可以使用 ruby​​ Rational 或 BigDecimal

在处理货币和货币兑换时,使用 money gem 也很常见.>

I'm testing a small and simple library I made in Ruby. The goal is to convert from EUR to CNY and vice versa. Simple.

I tested it to be sure everything works but I got an unexpected issue. When I use to_euro followed by to_yuan it should go back to the original amount ; it doesn't happen. I tried to .to_f or round(2) the amount variable which fix some tests, raise new ones, but it's never equal to what I expect globally ; I'm running out of idea to fix this :(

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

Tests

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

And here's my RSpec result

I'm pretty sure this problem is very common, any idea how to solve it easily ?

解决方案

Float isn't an exact number representation, as stated in the ruby docs:

Float objects represent inexact real numbers using the native architecture's double-precision floating point representation.

This not ruby fault, as floats can only be represented by a fixed number of bytes and therefor cannot store decimal numbers correctly.

Alternatively, you can use ruby Rational or BigDecimal

Its is also fairly common to use the money gem when dealing with currency and money conversion.

更多推荐

除法和乘法后浮点数不相等

本文发布于:2023-11-29 21:58:04,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1647741.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:除法   乘法   浮点数   不相等

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!