Question about division behavior

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Question about division behavior

Peter M. Goldstein
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
Reply | Threaded
Open this post in threaded view
|

Re: Question about division behavior

amiracam
interesting, I don't get the same results i.e. what I get checks with the expected MRI output

jruby 1.7.4 (1.9.3p392) 2013-05-17 fffffff on Java HotSpot(TM) 64-Bit Server VM 1.7.0_21-b12 [darwin-x86_64]
monteiro:~ charles$ irb
jruby-1.7.4 :001 > 30/1.05
 => 28.57142857142857 


Charles Monteiro



On Aug 22, 2013, at 1:51 PM, "Peter M. Goldstein" <[hidden email]> 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

Reply | Threaded
Open this post in threaded view
|

Re: Question about division behavior

keithrbennett
Me too:

jruby-1.7.4 :001 > 30/1.05
 => 28.57142857142857
jruby-1.7.4 :002 > RUBY_VERSION
 => "1.9.3"

- Keith


On Thu, Aug 22, 2013 at 2:35 PM, Charles Monteiro <[hidden email]> wrote:
interesting, I don't get the same results i.e. what I get checks with the expected MRI output

jruby 1.7.4 (1.9.3p392) 2013-05-17 fffffff on Java HotSpot(TM) 64-Bit Server VM 1.7.0_21-b12 [darwin-x86_64]
monteiro:~ charles$ irb
jruby-1.7.4 :001 > 30/1.05
 => 28.57142857142857 


Charles Monteiro



On Aug 22, 2013, at 1:51 PM, "Peter M. Goldstein" <[hidden email]> 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


Reply | Threaded
Open this post in threaded view
|

Re: Question about division behavior

Bruce Adams
In reply to this post by Peter M. Goldstein
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
Reply | Threaded
Open this post in threaded view
|

Re: Question about division behavior

Peter M. Goldstein
In reply to this post by keithrbennett
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.


On Thu, Aug 22, 2013 at 11:46 AM, Keith Bennett <[hidden email]> wrote:
Me too:


jruby-1.7.4 :001 > 30/1.05
 => 28.57142857142857
jruby-1.7.4 :002 > RUBY_VERSION
 => "1.9.3"

- Keith


On Thu, Aug 22, 2013 at 2:35 PM, Charles Monteiro <[hidden email]> wrote:
interesting, I don't get the same results i.e. what I get checks with the expected MRI output

jruby 1.7.4 (1.9.3p392) 2013-05-17 fffffff on Java HotSpot(TM) 64-Bit Server VM 1.7.0_21-b12 [darwin-x86_64]
monteiro:~ charles$ irb
jruby-1.7.4 :001 > 30/1.05
 => 28.57142857142857 


Charles Monteiro



On Aug 22, 2013, at 1:51 PM, "Peter M. Goldstein" <[hidden email]> 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



Reply | Threaded
Open this post in threaded view
|

Question about division behavior

Bruce Adams
Ah! Yes. There is an easy to reproduce bug with division and BigDecimal.

The fix, https://github.com/jruby/jruby/pull/797, is in master and will be released in 1.7.5.

Here is a possible workaround: https://github.com/jruby/jruby/issues/648#issuecomment-16623147.

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.
Reply | Threaded
Open this post in threaded view
|

Re: Question about division behavior

Peter M. Goldstein
Bruce,

Thanks for elucidating the issue.  I'll look into that workaround.

Best,

Peter


On Thu, Aug 22, 2013 at 3:00 PM, Bruce Adams <[hidden email]> wrote:
Ah! Yes. There is an easy to reproduce bug with division and BigDecimal.

The fix, https://github.com/jruby/jruby/pull/797, is in master and will be released in 1.7.5.

Here is a possible workaround: https://github.com/jruby/jruby/issues/648#issuecomment-16623147.

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.