monetize icon indicating copy to clipboard operation
monetize copied to clipboard

Ruby 3 Rounding Issue

Open caseyprovost opened this issue 2 years ago • 3 comments

Floats are now translated in interesting ways in Ruby 3. Take the following example:

# rails console or IRB

9.86.to_money => 
{
           :cents => 985.9999999999999,
    :currency_iso => "USD"
}

9.86.to_money.cents #=> 985.9999999999999

9.86.to_d(Float::DIG).to_money.cents #=> 986.0

What makes this more interesting is that not all numbers seem to be treated evenly.

# rails console or IRB

3.86.to_money.cents => #> 386.0

I am not sure if this is a bug in Float in ruby proper but I have found we change how we convert floats to money by transitioning to a BigDecimal using Float::DIG...all our rounding issues went away on Ruby 3.

Is this something we should have a PR for here? Or should I be submitting a bug to Ruby?

caseyprovost avatar Dec 14 '21 14:12 caseyprovost

Floats are now translated in interesting ways in Ruby 3. Take the following example:

# rails console or IRB

9.86.to_money => 
{
           :cents => 985.9999999999999,
    :currency_iso => "USD"
}

9.86.to_money.cents #=> 985.9999999999999

9.86.to_d(Float::DIG).to_money.cents #=> 986.0

What makes this more interesting is that not all numbers seem to be treated evenly.

# rails console or IRB

3.86.to_money.cents => #> 386.0

I am not sure if this is a bug in Float in ruby proper but I have found we change how we convert floats to money by transitioning to a BigDecimal using Float::DIG...all our rounding issues went away on Ruby 3.

Is this something we should have a PR for here? Or should I be submitting a bug to Ruby?

OsvaldoRino avatar Feb 15 '22 03:02 OsvaldoRino

I can't reproduce this with Ruby 3.1:

irb(main):001:0> 9.86.to_money
=> #<Money fractional:986 currency:USD>
irb(main):002:0> 9.86.to_money.cents
=> 986
irb(main):003:0> 9.86.to_d(Float::DIG).to_money.cents
=> 986
irb(main):004:0> RUBY_VERSION
=> "3.1.0"
irb(main):005:0> Gem.loaded_specs['monetize'].version
=> Gem::Version.new("1.12.0")
irb(main):006:0> Gem.loaded_specs['money'].version
=> Gem::Version.new("6.16.0")

Has this already been fixed or am I missing something?

lenlo avatar Feb 16 '22 05:02 lenlo

I'm on Ruby 3.0.1 and don't see this issue.

irb(main):001:0> 9.86.class
=> Float
irb(main):002:0> 9.86.to_money.cents
=> 986
irb(main):003:0> 9.86.to_money
=> #<Money fractional:986 currency:USD>
irb(main):004:0> 9.86.to_money.cents
=> 986
irb(main):005:0> 9.86.to_d(Float::DIG).to_money.cents
=> 986
irb(main):007:0> RUBY_VERSION
=> "3.0.1"
irb(main):008:0> Gem.loaded_specs['monetize'].version
=> Gem::Version.new("1.12.0")
irb(main):009:0> Gem.loaded_specs['money'].version
=> Gem::Version.new("6.16.0")

nitsujri avatar Feb 23 '22 08:02 nitsujri