I’m in the process of add JRuby support to a gem, and I ran into a
surprising behavior that I believe may be a bug. Specifically, the
division operation is not giving me a correct result with an integer
numerator and a denominator that is an expression that results in a
rational, non-integer value.

In a test case in the gem, a value was being calculated from two
variables:

total: 30
rate: 0.05

And the result being calculated is:

result = total / (1 + rate)

Using JRuby 1.7.4 (1.9.3p392) 2013-05-16, this result is zero
Using MRI 2.0.0-p247 (and presumably earlier MRI rubies, as this test
case
has been in place for a while), this result is 28.57142857142857

I can force JRuby to calculate the expected value (to some precision) by
forcing total to a float -

result = total.to_f / (1 + rate)

But in my view this shouldn’t be necessary, and it isn’t consistent with
MRI behavior.

I’m not entirely clear why JRuby is behaving in this fashion, and to me
it
looks like a bug. Can anyone shed any light?

Can you give us more context? Maybe share the source code for your gem,
ideally with a failing test?

Doing exactly what you describe behaves fine for me:

$ ruby -v
jruby 1.7.4 (1.9.3p392) 2013-05-16 2390d3b on OpenJDK 64-Bit Server VM
1.7.0_25-b30 [linux-amd64]
$ irb
irb(main):001:0> total = 30
=> 30
irb(main):002:0> rate = 0.05
=> 0.05
irb(main):003:0> result = total / (1 + rate)
=> 28.57142857142857
irb(main):004:0> result
=> 28.57142857142857
irb(main):005:0>

On Thursday, August 22, 2013, Peter M. Goldstein wrote:

Hi All,
I'm in the process of add JRuby support to a gem, and I ran into a
surprising behavior that I believe may be a bug. Specifically, the
division operation is not giving me a correct result with an integer
numerator and a denominator that is an expression that results in a
rational, non-integer value.
In a test case in the gem, a value was being calculated from two
variables:
total: 30
rate: 0.05
And the result being calculated is:
result = total / (1 + rate)
Using JRuby 1.7.4 (1.9.3p392) 2013-05-16, this result is zero
Using MRI 2.0.0-p247 (and presumably earlier MRI rubies, as this
test case has been in place for a while), this result
is 28.57142857142857
I can force JRuby to calculate the expected value (to some
precision) by forcing total to a float -
result = total.to_f / (1 + rate)
But in my view this shouldn't be necessary, and it isn't consistent
with MRI behavior.
I'm not entirely clear why JRuby is behaving in this fashion, and to
me it looks like a bug. Can anyone shed any light?
Thanks.
Best,
Peter

On Thursday, August 22, 2013, Peter M. Goldstein wrote:

I think the key is that total is a BigDecimal, not an integer, which
I didn't realize until I ran some Pry inspection. See below for
details.
The gem is spree/spree, master branch. I've got a JRuby compatible
branch here -
https://github.com/petergoldstein/spree/tree/feature/add_jruby_to_travis
. Note that branch already includes the forced .to_f on total.
The failing test can be found at
spree/core/spec/models/spree/calculator/default_tax_spec.rb:64
Here's some Pry output from a binding call just before the method
runs into trouble. As you can
From:
/Users/peter/Development/apps/petergoldstein/spree/core/app/models/spree/calculator/default_tax.rb
@ line 51 Spree::Calculator::DefaultTax#deduced_total_by_rate:
50: def deduced_total_by_rate(total, rate)
=> 51: binding.pry
52: round_to_two_places(total - ( total / (1 + rate.amount) )

)
53: end

[1] pry(#<Spree::Calculator::DefaultTax>)> total / (1 + rate.amount)
=> #<BigDecimal: 30.0>
[2] pry(#<Spree::Calculator::DefaultTax>)> total
=> #<BigDecimal: 30.0>
[3] pry(#<Spree::Calculator::DefaultTax>)> rate
=> #<Spree::TaxRate:0x6ab6 @name="Spree::TaxRate_1001">
[4] pry(#<Spree::Calculator::DefaultTax>)> rate.amount
=> 0.05
[5] pry(#<Spree::Calculator::DefaultTax>)> 1 + rate.amount
=> 1.05
[6] pry(#<Spree::Calculator::DefaultTax>)> 30/1.05
=> 28.57142857142857
[7] pry(#<Spree::Calculator::DefaultTax>)> rate.amount.class
=> Float
[8] pry(#<Spree::Calculator::DefaultTax>)> total.class
=> BigDecimal
[9] pry(#<Spree::Calculator::DefaultTax>)> BigDecimal.new(30)
=> #<BigDecimal: 30.0>
[10] pry(#<Spree::Calculator::DefaultTax>)> BigDecimal.new(30)/1.05
=> #<BigDecimal: 30.0>
Note that total is actually a BigDecimal, which appears to be key to
the issue.