BigDecimal#hash returns different value for numerically equal numbers #772

Closed
ananthakumaran opened this Issue May 26, 2013 · 3 comments

Projects

None yet

3 participants

@ananthakumaran

jruby

irb(main):003:0> BigDecimal.new("2").hash == BigDecimal.new("2.0").hash
=> false
irb(main):004:0> BigDecimal.new("2") == BigDecimal.new("2.0")
=> true
irb(main):005:0> BigDecimal.new("2").eql?(BigDecimal.new("2.0"))
=> true

mri

1.9.3p125 :002 > BigDecimal.new('2').hash == BigDecimal.new('2.0').hash
 => true
1.9.3p125 :003 > BigDecimal.new('2') == BigDecimal.new('2.0')
 => true
1.9.3p125 :004 > BigDecimal.new('2').eql?(BigDecimal.new('2.0'))
 => true
@headius
Member
headius commented May 26, 2013

MRI must be using a different mechanism than us for calculating the hash of BigDecimal. In JRuby, they are both using the JDK's implementation, i.e. java.math.BigDecimal#hashCode. One wonders why the JDK folks did not want equal values to hash the same...it is worth investigating before we go off implementing MRI's behavior. For what it's worth, these are two distinct BigDecimals, since "2" only has one significant figure and "2.0" has two.

@atambo
Member
atambo commented Jun 22, 2013

According to the BigDecimal#hashCode javadocs:

Note that two BigDecimal objects that are numerically equal but differ in scale (like 2.0 and 2.00) will generally not have the same hash code.

And an easy solution to this would be to call BigDecimal#stripTrailingZeros before calling BigDecimal#hashCode. @headius, does that sound like the right thing to do? If so, I can put together the patch and specs.

@headius
Member
headius commented Jun 22, 2013

I'm not comfortable with stripping trailing zeros in general, but stripping just for hashCode purposes might be acceptable. I wish there were a zero-allocation way to get a stripped hashCode from BigDecimal though.

@atambo atambo closed this in 7c8bbf2 Jun 22, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment